2011-03-11 153 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