在lxml中更改元素名称空间 [英] changing element namespace in lxml

查看:78
本文介绍了在lxml中更改元素名称空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于lxml,我不确定如何正确删除现有元素的命名空间并设置一个新元素.

With lxml, I am not sure how to properly remove the namespace of an existing element and set a new one.

例如,我正在解析这个最小的xml文件:

For instance, I'm parsing this minimal xml file:

<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>

使用lxml:

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

如果我检查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'

对于标签,只需设置正确的字符串即可. nsmap怎么样?

As for the tag, it's just a matter of setting the right string. How about nsmap?

推荐答案

我同意mzjn和Parfait;我将使用XSLT更改名称空间.

I agree with mzjn and 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.

示例...

XML输入(input.xml)

XML Input (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

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"))

输出

<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>

您得到此输出...

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

有关将XSLT与以下功能结合使用的更多信息,请参见 https://lxml.de/xpathxslt.html lxml.

See https://lxml.de/xpathxslt.html for more info on using XSLT with lxml.

这篇关于在lxml中更改元素名称空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆