2011-03-11 157 views
14

我有一个150 MB(它甚至可能更多)XML文件。我需要删除所有的命名空间。 它在Visual Basic 6.0上,所以我使用DOM来加载XML。加载是好的,我一开始怀疑,但不知何故,这部分工作正常。如何使用XSLT从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> 
+0

可能重复[如何从XML与C#中删除所有命名空间?(http://stackoverflow.com/questions/987135/how-to-remove-all-namespaces-from-xml-with-c) – 2011-03-27 00:46:23

回答

23

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

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

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

...和代码:

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

你也可以使用<xsl:template match="node()">的而不是最后一个模板,但那么你应该使用priority属性,以防止匹配该模板的元素。

1

如何在其中包含属性?

这个模板只是追加到你已经有了一个:

<xsl:template match="@*"> 
    <xsl:copy/> 
</xsl:template> 
-2
<?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" encoding="UTF-8"/> 
<xsl:template match="/"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 
<xsl:template match="@*"> 
    <xsl:attribute name="{local-name()}"> 
     <xsl:value-of select="current()"/> 
    </xsl:attribute> 
</xsl:template> 
<xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="@* | * | text()"/> 
    </xsl:element> 
</xsl:template> 
<xsl:template match="text()"> 
    <xsl:copy> 
     <xsl:value-of select="current()"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 
+2

如果你在你的代码中添加一些解释,那将会很好。 – zx485 2016-11-18 18:59:49