2010-12-02 85 views
2

我想使用xslt转换输入xml文件,以更改可以出现在xml树的不同位置的特定元素的名称。如何从属于它们的非空名称空间中删除名称?

我有一个像下面这样的XML,

<catalog> 
<cd> 
    <ost:title>Empire Burlesque</ost:title> 
    <artist>Bob Dylan</artist> 
    <country>USA</country> 
    <company> 
    <ost:name>Columbia<ost:name> 
    </company> 
    <price>10.90</price> 
    <year>1985</year> 
</cd> 
</catalog> 

我想删除所有“OST:”从所有元素前缀,因为它是使用XSLT保持一切。一个示例代码将不胜感激。

+0

缩进4个空格或使用101010按钮输入代码。我为你修好了。 – 2010-12-02 05:05:07

+0

你好,是的,我们有ost的名字空间。实际上,我们希望将xml恢复到不支持此ost名称空间的以前版本。感谢您的回复 – Hasif 2010-12-02 05:13:29

回答

2

在您的示例中,您似乎没有其他要删除的名称空间。所以,下面是一个XSLT样式表的示例,它从元素中删除了所有名称空间(不仅仅是您的ost:)。

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

    <!-- identity template: copy everything as is... --> 
    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <!-- ... except for elements, 
     create a similarly named element without a namespace --> 
    <xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 

它使用identity transformation复制一切按原样,但是将覆盖为元素,创造出具有相同本地名的元素,但没有命名空间。

如果您只想删除ost:名称空间,则可以包含该名称空间的名称空间声明,并将后一个模板更改为匹配ost:*

0

这种转变是最一般的。它从全局参数中指定的名称空间中删除所有元素和属性。它也消除了那些这些命名空间之一所有名称空间节点:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my" > 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<my:delNs> 
    <ns>some:namespace1</ns> 
    <ns>some:namespace3</ns> 
</my:delNs> 

<xsl:variable name="vdelNS" 
    select="document('')/*/my:delNs/*"/> 

<xsl:template match="*"> 
    <xsl:element name="{name()}" namespace="{namespace-uri()}"> 
    <xsl:copy-of select="namespace::*[not(.=$vdelNS)]"/> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="@*"> 
    <xsl:copy-of select="."/> 
</xsl:template> 

<xsl:template priority="10" match= 
"*[namespace-uri()=document('')/*/my:delNs/*]"> 

    <xsl:element name="{local-name()}"> 
    <xsl:copy-of select="namespace::*[not(.=$vdelNS)]"/> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match= 
"@*[namespace-uri()=document('')/*/my:delNs/*]"> 
    <xsl:attribute name="{local-name()}"> 
    <xsl:value-of select="."/> 
    </xsl:attribute> 
</xsl:template> 
</xsl:stylesheet> 

当这种转变是在下面的XML文档施加(基于所提供的,但是校正为良好和扩展为包含3个命名空间和在其中的元素和属性):

<catalog xmlns:ost="some:namespace1" 
    xmlns:x="some:namespace2" 
    xmlns:y="some:namespace3"> 
<cd> 
    <ost:title>Empire Burlesque</ost:title> 
    <y:artist>Bob Dylan</y:artist> 
    <country>USA</country> 
    <company ost:type="big"> 
    <ost:name>Columbia</ost:name> 
    </company> 
    <x:price>10.90</x:price> 
    <year>1985</year> 
</cd> 
</catalog> 

有用结果产生

<catalog xmlns:x="some:namespace2"> 
    <cd> 
     <title>Empire Burlesque</title> 
     <artist>Bob Dylan</artist> 
     <country>USA</country> 
     <company type="big"> 
     <name>Columbia</name> 
     </company> 
     <x:price>10.90</x:price> 
     <year>1985</year> 
    </cd> 
</catalog> 

说明

  1. 前两个模板是几乎等同于身份的规则,但他们不复制命名空间节点为<my:delNs>指定的命名空间。

  2. 最后两个模板适用于属于<my:delNs>下列出的名称空间的所有元素和属性。只有在这两个模板名称实际上更改为只有本地名称。

相关问题