简体   繁体   English

更改 lxml 中的元素命名空间

[英]changing element namespace in lxml

With lxml , I am not sure how to properly remove the namespace of an existing element and set a new one.使用lxml ,我不确定如何正确删除现有元素的命名空间并设置一个新元素。

For instance, I'm parsing this minimal xml file:例如,我正在解析这个最小的 xml 文件:

<myroot xmlns="http://myxml.com/somevalue">
    <child1>blabla</child1>
    <child2>blablabla</child2>
</myroot>

... and I'd like it to become: ......我希望它变成:

<myroot xmlns="http://myxml.com/newvalue">
    <child1>blabla/child1>
    <child2>blablabla</child2>
</myroot>

With lxml :使用lxml

from lxml import etree as ET
tree = ET.parse('myfile.xml')
root= tree.getroot()

If I inspect root :如果我检查root

In [7]: root
Out[7]: <Element {http://myxml.com/somevalue}myroot at 0x7f6e13832588>
In [8]: root.nsmap
Out[8]: {None: 'http://myxml.com/somevalue'}
In [11]: root.tag
Out[11]: '{http://myxml.com/somevalue}myroot'

Ideally, I would like to end up with:理想情况下,我想结束:

In [8]: root.nsmap
Out[8]: {None: 'http://myxml.com/newvalue'}
In [11]: root.tag
Out[11]: '{http://myxml.com/newvalue}myroot'

As for the tag, it's just a matter of setting the right string.至于标签,只需设置正确的字符串即可。 How about nsmap ? nsmap怎么nsmap

I agree with mzjn and Parfait;我同意 mzjn 和 Parfait; I'd use XSLT to change the namespace.我会使用 XSLT 来更改命名空间。

You can make the XSLT fairly reusable by having the old and new namespaces passed in as parameters.通过将新旧名称空间作为参数传入,可以使 XSLT 具有相当的可重用性。

Example...例子...

XML Input (input.xml) XML 输入(input.xml)

<myroot xmlns="http://myxml.com/somevalue">
    <child1>blabla</child1>
    <child2>blablabla</child2>
</myroot>

XSLT 1.0 (test.xsl) XSLT 1.0 (test.xsl)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="orig_namespace"/>
  <xsl:param name="new_namespace"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*" priority="1">
    <xsl:choose>
      <xsl:when test="namespace-uri()=$orig_namespace">
        <xsl:element name="{name()}" namespace="{$new_namespace}">
          <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

Python Python

from lxml import etree

tree = etree.parse("input.xml")
xslt = etree.parse("test.xsl")

orig_namespace = "http://myxml.com/somevalue"
new_namespace = "http://myxml.com/newvalue"

new_tree = tree.xslt(xslt, orig_namespace=f"'{orig_namespace}'",
                     new_namespace=f"'{new_namespace}'")
print(etree.tostring(new_tree, pretty_print=True).decode("utf-8"))

Output输出

<myroot xmlns="http://myxml.com/newvalue">
  <child1>blabla</child1>
  <child2>blablabla</child2>
</myroot>

Also, if you use the following input (that uses a namespace prefix)...此外,如果您使用以下输入(使用命名空间前缀)...

<ns1:myroot xmlns:ns1="http://myxml.com/somevalue">
    <ns1:child1>blabla</ns1:child1>
    <ns1:child2>blablabla</ns1:child2>
</ns1:myroot>

you get this output...你得到这个输出...

<ns1:myroot xmlns:ns1="http://myxml.com/newvalue">
  <ns1:child1>blabla</ns1:child1>
  <ns1:child2>blablabla</ns1:child2>
</ns1:myroot>

See https://lxml.de/xpathxslt.html for more info on using XSLT with lxml.有关在 lxml 中使用 XSLT 的更多信息,请参阅https://lxml.de/xpathxslt.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM