代码之家  ›  专栏  ›  技术社区  ›  Parris

python:目录结构的XML表示,递归

  •  5
  • Parris  · 技术社区  · 16 年前

    所以我尝试使用os.walk()生成目录结构的XML表示。我好像收到了很多副本。对于XML文件的第一部分,它正确地将目录放置在彼此之间,并将文件放置在正确的位置;但是,在正确地放置之后,它将继续错误地遍历。我不太清楚为什么……

    这是我的代码:

    def dirToXML(self,directory):
            curdir = os.getcwd()
            os.chdir(directory)
            xmlOutput=""
    
            tree = os.walk(directory)
            for root, dirs, files in tree:
                pathName = string.split(directory, os.sep)
                xmlOutput+="<dir><name><![CDATA["+pathName.pop()+"]]></name>"
                if len(files)>0:
                    xmlOutput+=self.fileToXML(files)
                for subdir in dirs:
                    xmlOutput+=self.dirToXML(os.path.join(root,subdir))
                xmlOutput+="</dir>"
    
            os.chdir(curdir)
            return xmlOutput  
    

    filetoxml,只需解析列表,所以不需要担心这个问题。

    目录结构很简单:

    images/
    images/testing.xml
    images/structure.xml
    images/Hellos
    images/Goodbyes
    images/Goodbyes/foo
    images/Goodbyes/bar
    images/Goodbyes/square
    

    结果XML文件变成:

    <structure>
    <dir>
    <name>images</name>
      <files>
        <file>
          <name>structure.xml</name>
        </file>
        <file>
          <name>testing.xml</name>
        </file>
      </files>
      <dir>
        <name>Hellos</name>
      </dir>
      <dir>
        <name>Goodbyes</name>
        <dir>
          <name>foo</name>
        </dir>
        <dir>
          <name>bar</name>
        </dir>
        <dir>
          <name>square</name>
        </dir>
      </dir>
      <dir>
        <name>foo</name>
      </dir>
      <dir>
        <name>bar</name>
      </dir>
      <dir>
          <name>square</name>
        </dir>
      </dir>
      <dir>
        <name>Hellos</name>
      </dir>
      <dir>
        <name>Goodbyes</name>
        <dir>
          <name>foo</name>
        </dir>
        <dir>
          <name>bar</name>
        </dir>
        <dir>
          <name>square</name>
        </dir>
      </dir>
      <dir>
        <name>foo</name>
      </dir>
      <dir>
        <name>bar</name>
      </dir>
      <dir>
        <name>square</name>
      </dir>
    </structure>
    

    任何帮助都将不胜感激!

    3 回复  |  直到 16 年前
        1
  •  8
  •   Mike DeSimone    16 年前

    我建议不要使用 os.walk() 因为你要做那么多按摩它的输出。相反,只需使用使用 os.listdir() , os.path.join() , os.path.isdir() 等。

    import os
    from xml.sax.saxutils import escape as xml_escape
    
    def DirAsXML(path):
        result = '<dir>\n<name>%s</name>\n' % xml_escape(os.path.basename(path))
        dirs = []
        files = []
        for item in os.listdir(path):
            itempath = os.path.join(path, item)
            if os.path.isdir(itempath):
                dirs.append(item)
            elif os.path.isfile(itempath):
                files.append(item)
        if files:
            result += '  <files>\n' \
                + '\n'.join('    <file>\n      <name>%s</name>\n    </file>'
                % xml_escape(f) for f in files) + '\n  </files>\n'
        if dirs:
            for d in dirs:
                x = DirAsXML(os.path.join(path, d))
                result += '\n'.join('  ' + line for line in x.split('\n'))
        result += '</dir>'
        return result
    
    if __name__ == '__main__':
        print '<structure>\n' + DirAsXML(os.getcwd()) + '\n</structure>'
    

    就我个人而言,我建议使用一个更不冗长的XML模式,将名称放入属性中,并去掉 <files> 组:

    import os
    from xml.sax.saxutils import quoteattr as xml_quoteattr
    
    def DirAsLessXML(path):
        result = '<dir name=%s>\n' % xml_quoteattr(os.path.basename(path))
        for item in os.listdir(path):
            itempath = os.path.join(path, item)
            if os.path.isdir(itempath):
                result += '\n'.join('  ' + line for line in 
                    DirAsLessXML(os.path.join(path, item)).split('\n'))
            elif os.path.isfile(itempath):
                result += '  <file name=%s />\n' % xml_quoteattr(item)
        result += '</dir>'
        return result
    
    if __name__ == '__main__':
        print '<structure>\n' + DirAsLessXML(os.getcwd()) + '\n</structure>'
    

    这会产生如下输出:

    <structure>
    <dir name="local">
      <dir name=".hg">
        <file name="00changelog.i" />
        <file name="branch" />
        <file name="branch.cache" />
        <file name="dirstate" />
        <file name="hgrc" />
        <file name="requires" />
        <dir name="store">
          <file name="00changelog.i" />
    

    等。

    如果 () 工作更像 expat 回拨电话,你会更轻松的。

        2
  •  6
  •   oefe    16 年前

    拆下两条线:

            for subdir in dirs:
                xmlOutput+=self.dirToXML(os.path.join(root,subdir))
    

    您正在递归到子目录中,但这是多余的,因为os.walk会自己递归。

        3
  •  0
  •   Parris    16 年前

    我试图使用os.walk,但我发现它不适用于我想在XML中创建的递归树结构。我修改了我的代码如下,它产生了我需要的结果:

    def dirToXML(self,directory):
            curdir = os.getcwd()
            os.chdir(directory)
            xmlOutput=""
    
            pathName = string.split(directory, os.sep)
            xmlOutput+="<dir><name><![CDATA["+pathName.pop()+"]]></name>"
            for item in os.listdir(directory):
                if os.path.isfile(os.path.join(directory, item)):
                    xmlOutput+="<file><name><![CDATA["+item+"]]></name></file>"
                else :
                    xmlOutput+=self.dirToXML(os.path.join(directory,item))
            xmlOutput+="</dir>"
    
            os.chdir(curdir)
            return xmlOutput    
    
    推荐文章