类似于lxml的tostring(method ='text')返回没有文本内容的xml?

时间:2013-05-01 12:21:31

标签: python xml lxml

是否有类似于lxml的{​​{1}}将返回XML文档结构/节点但删除这些节点中的文本内容?我希望快速获取文档的层次结构以供审阅,而不需要任何内容​​本身。删除属性也是有益的。

2 个答案:

答案 0 :(得分:1)

您可以使用XSLT复制所有节点,但删除属性和文本:

import lxml.etree as ET

content = '''\
<root>
<foo col1="a1">
    Remove
    <bar col7="A"/>this
    <bar col7="A1"/>text
</foo>
<foo col1="b1">
    <bar col7="B"/>
</foo>
<foo col1="c2">
</foo>
</root>'''

root = ET.fromstring(content)
xslt = '''\
    <xsl:stylesheet version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="no"/>


<!-- Copy everything -->
<xsl:template match="@*|node()|text()|comment()|processing-instruction()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()|text()|comment()|processing-instruction()"/>
    </xsl:copy>
</xsl:template>

<!-- To remove attributes or nodes, simply write a matching template that
     doesn't do anything. Therefore, it is removed -->
<xsl:template match="text()"/>  <!-- Remove text -->
<xsl:template match="@*"/>      <!-- Remove all attributes -->
    </xsl:stylesheet>
'''
xslt_doc = ET.fromstring(xslt)
transform = ET.XSLT(xslt_doc)
tree = transform(root)

print(ET.tostring(tree))

产量

<root><foo><bar/><bar/></foo><foo><bar/></foo><foo/></root>

XSLT源自this

或者,对于漂亮的印刷:

print(ET.tostring(tree, pretty_print=True))

产量

<root>
  <foo>
    <bar/>
    <bar/>
  </foo>
  <foo>
    <bar/>
  </foo>
  <foo/>
</root>

答案 1 :(得分:1)

您可以使用.iterwalk()方法为元素生成事件,然后自己打印出结构:

indent = []
for action, elem in etree.iterwalk(root, events=('start', 'end')):
    if action == 'start':
        print '{}<{}{}>'.format(''.join(indent), elem.tag, '/' if not len(elem) else '')
        indent.append('  ')
    else:
        indent.pop()
        if len(elem):
            print '{}</{}>'.format(''.join(indent), elem.tag)

这使用两个空格的缩进来传达结构,但您可以轻松地进行调整。

示例输出:

<root>
  <foo>
    <bar/>
    <bar/>
  </foo>
  <foo>
    <bar/>
  </foo>
  <foo/>
</root>