【问题标题】:Remove all namespaces from xml从 xml 中删除所有命名空间
【发布时间】:2020-08-30 04:54:47
【问题描述】:

有没有办法从 xml 中删除命名空间(我知道没有任何名称冲突)?目前我正在为每个已知的命名空间执行此操作:

s = re.sub(r'(<\/?)md:', r'\1', s)             # remove md:
s = re.sub(r'\s+xsi:', ' ', s)                 # remove xsi:

但我想知道是否可以使用更通用的东西。特定 xml 中不允许有 CDATA。

【问题讨论】:

  • 你永远不需要它,当你使用 xml 解析器时,你总是可以指定所有必需的命名空间。
  • @WiktorStribiżew 是的,问题是有很多命名空间,并不是我知道的全部(例如,可能会添加未来的命名空间),所以这更通用现在。到目前为止,它每天可以处理约 100 万份文档。
  • 您可以使用 XSLT 处理来可靠地实现这一点。只需将身份模板与将name()s 转换为local-name()s 的模板结合使用。然后从 Python 调用 XSLT。
  • @zx485 这是一个有趣的方法,感谢您的反馈。您能否添加一个答案来说明您将如何做到这一点?

标签: python regex xml


【解决方案1】:

您可以通过从 Python 调用以下 XSLT-1.0 模板来使用 XSLT 方法。它将身份模板与将元素的(完整)name()s 仅转换为它们的local-name()s 的模板相结合。例如,这意味着所有&lt;ns1:abc&gt; 元素都将转换为&lt;abc&gt;。命名空间被省略。

但是,这有多大用处取决于您的用例。它减少了信息量,因此请小心处理。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="node()|@*">   <!-- Identity template copies all nodes (except for elements, which are handled by the other template) -->
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

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

</xsl:stylesheet>

将它与 XSLT-1.0(或更高版本)框架/处理器一起应用。

【讨论】: