lxml etree xmlparser 删除不需要的命名空间

新手上路,请多包涵

我有一个 xml 文档,我正在尝试使用 Etree.lxml 进行解析

<Envelope xmlns="http://www.example.com/zzz/yyy">
  <Header>
    <Version>1</Version>
  </Header>
  <Body>
    some stuff
  <Body>
<Envelope>

我的代码是:

 path = "path to xml file"
from lxml import etree as ET
parser = ET.XMLParser(ns_clean=True)
dom = ET.parse(path, parser)
dom.getroot()

当我尝试获取 dom.getroot() 时,我得到:

 <Element {http://www.example.com/zzz/yyy}Envelope at 28adacac>

但是我只想:

 <Element Envelope at 28adacac>

当我做

dom.getroot().find("Body")

我没有得到任何回报。然而,当我

dom.getroot().find("{http://www.example.com/zzz/yyy}Body")

我得到一个结果。

我认为将 ns_clean=True 传递给解析器会阻止这种情况。

有任何想法吗?

原文由 Mark 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 693
2 个回答
import io
import lxml.etree as ET

content='''\
<Envelope xmlns="http://www.example.com/zzz/yyy">
  <Header>
    <Version>1</Version>
  </Header>
  <Body>
    some stuff
  </Body>
</Envelope>
'''
dom = ET.parse(io.BytesIO(content))

您可以使用 xpath 方法找到命名空间感知节点:

 body=dom.xpath('//ns:Body',namespaces={'ns':'http://www.example.com/zzz/yyy'})
print(body)
# [<Element {http://www.example.com/zzz/yyy}Body at 90b2d4c>]

如果你真的想删除命名空间,你可以使用 XSL 转换:

 # http://wiki.tei-c.org/index.php/Remove-Namespaces.xsl
xslt='''<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="no"/>

<xsl:template match="/|comment()|processing-instruction()">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>

<xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
      <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>
</xsl:stylesheet>
'''

xslt_doc=ET.parse(io.BytesIO(xslt))
transform=ET.XSLT(xslt_doc)
dom=transform(dom)

在这里我们看到名称空间已被删除:

 print(ET.tostring(dom))
# <Envelope>
#   <Header>
#     <Version>1</Version>
#   </Header>
#   <Body>
#     some stuff
#   </Body>
# </Envelope>

所以你现在可以通过这种方式找到 Body 节点:

 print(dom.find("Body"))
# <Element Body at 8506cd4>

原文由 unutbu 发布,翻译遵循 CC BY-SA 3.0 许可协议

尝试使用 Xpath:

 dom.xpath("//*[local-name() = 'Body']")

取自(并简化) 此页面,在“xpath() 方法”部分下

原文由 dusan 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏