0

是否有类似的lxml'setree.tostring(..., method='text')将返回 XML 文档结构/节点但删除这些节点中的文本内容?我正在寻找快速获取文档的层次结构以进行审查,而无需任何内容本身。删除属性也将是有益的。

4

2 回答 2

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 就是从这个.

或者,为了漂亮的打印:

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

产量

<root>
  <foo>
    <bar/>
    <bar/>
  </foo>
  <foo>
    <bar/>
  </foo>
  <foo/>
</root>
于 2013-05-01T12:37:47.190 回答
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>
于 2013-05-01T12:38:08.983 回答