2011-04-08 127 views
4

嗨我正在写一个XSLT,并在其中使用<xsl:copy-of>函数。现在,当它被执行时,来自XML的namesapce也被复制。为了删除我使用的功能,如<xsl:copy-of select="$RootNode/Child" copy-namespaces="no"/>。但是如果Child有更多的子元素,那么名称空间就出现在那里。所以任何人都可以请告诉我如何删除。 下面是我使用的xslt和XML的片段。命名空间从XSLT中删除

<xsl:template match="/"> 
    <xsl:element name="Parent"> 
    <xsl:copy-of select="Child" copy-namespaces="no"/> 
    </xsl:element> 

和XML是:

<Child> 
<GrandChild> 
<PhoneNumberType>DayPhone</PhoneNumberType> 
</GrandChild></Child> 

命名空间中不出现CustomerParty,但它们存在于儿童,但他们在目前的孙子辈。

+1

问得好,+1。请参阅我的答案以获得解释和完整,简短的解决方案。 :) – 2011-04-08 13:13:20

+0

Vivek:我的回答对你有用吗?你还有什么问题吗?请告诉我。 – 2012-05-31 22:01:31

回答

9

copy-namespaces="no"属性不去掉所有名称空间节点 - 如在XSLT 2.0 spec注意到:

如果需要的值没有,则没有一个命名空间节点的复制:然而,命名空间节点仍然会按照命名空间修复过程的要求在结果树中创建:请参见5.7.3命名空间修复。此属性影响由此指令复制的所有元素:两个元素都由选择表达式直接选择,而元素是由选择表达式选择的节点的后代。

下面是一个例子,如何摆脱所有的(非强制)命名空间节点的:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

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

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

当这个一般变换此XML文档的应用:

<x:nums xmlns:x="my:x"> 
    <x:num>01</x:num> 
    <x:num>02</x:num> 
    <x:num>03</x:num> 
    <x:num>04</x:num> 
    <x:num>05</x:num> 
    <x:num>06</x:num> 
    <x:num>07</x:num> 
    <x:num>08</x:num> 
    <x:num>09</x:num> 
    <x:num>10</x:num> 
</x:nums> 

想要的,产生正确的结果:

<nums> 
    <num>01</num> 
    <num>02</num> 
    <num>03</num> 
    <num>04</num> 
    <num>05</num> 
    <num>06</num> 
    <num>07</num> 
    <num>08</num> 
    <num>09</num> 
    <num>10</num> 
</nums> 

请注意

  1. 转型是不是XSLT-2.0 - 特有的,可以用XSLT 1.0使用了。

  2. 删除所有命名空间节点通常是一个不安全的进程,因为来自不同命名空间的节点都放在“无命名空间”中。在这个过程中,某些属性可能会丢失,并且过程通常不可逆(不是1:1)。

+0

+1正确答案。但我认为你的意思是[保留前缀和名称空间名称](http://www.w3.org/TR/xml-names/#xmlReserved)而不是_“mandatory”_ – 2011-04-08 16:30:25

+0

@Ajjandro:是的。 – 2011-04-08 16:54:11

0

有了这个模板,你应该能够删除的命名空间:

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

另请参考:http://www.devang-gandhi.net/blog/remove-namespace-attribute-from-xml-root-xslt/

这是否帮助你解决问题?

最好的问候, 彼得

+0

该代码段不处理名称空间中的属性。 – 2011-04-08 13:15:21

+0

@Dimitre:你说得对Dimitre。谢谢您的回答。 (+1)我只是看着那个并意识到它。到目前为止,我只需要这几次,它总是为我工作,只从元素中删除名称空间。我将它添加到我的最爱,所以我记得;-) – Peter 2011-04-08 13:20:42

+0

不客气。 – 2011-04-08 15:48:08