如何使用XSLT从XML中删除命名空间

Gan*_*shT 21 xml xslt xml-namespaces

我有150 MB(有时甚至更多)XML文件.我需要删除所有名称空间.它在Visual Basic 6.0上,所以我使用DOM来加载XML.加载是可以的,我一开始对此持怀疑态度,但不知何故,这部分工作正常.

我正在尝试以下XSLT,但它也删除了所有其他属性.我想保留所有属性和元素,我只需要删除命名空间.显然这是因为我有xsl:element但没有属性.我如何在那里包含属性?

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="UTF-8" />
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

jas*_*sso 32

您的XSLT也会删除属性,因为您没有可以复制它们的模板.<xsl:template match="*">仅匹配元素,而不匹配属性(或文本,注释或处理指令).

下面是一个样式表,它从已处理的文档中删除所有名称空间定义,但复制所有其他节点和值:元素,属性,注释,文本和处理指令.请注意2件事

  1. 如此复制属性不足以删除所有名称空间.即使包含元素不属于命名空间,属性也可以属于命名空间.因此,还需要创建属性,如元素.使用<xsl:attribute>元素创建属性.
  2. 有效的XML文档不能包含具有两个或多个具有相同扩展名称的属性的元素,但如果属性具有不同的名称空间,则元素可以包含具有相同本地名称的多个属性.这意味着从属性名称中删除名称空间前缀将导致dataloss,如果有一个元素具有两个具有相同本地名称的属性.其他一个属性将被删除(或覆盖).

......和代码:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>

    <!-- Stylesheet to remove all namespaces from a document -->
    <!-- NOTE: this will lead to attribute name clash, if an element contains
        two attributes with same local name but different namespace prefix -->
    <!-- Nodes that cannot have a namespace are copied as such -->

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

    <!-- template to copy attributes -->
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <!-- template to copy the rest of the nodes -->
    <xsl:template match="comment() | text() | processing-instruction()">
        <xsl:copy/>
    </xsl:template>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

您也可以使用<xsl:template match="node()">而不是最后一个模板,但是您应该使用priority属性来阻止元素与此模板匹配.