XSLT 1.0将命名空间移动到子节点

问题描述:

我只能访问xpath 1.0命令和函数。我需要将名称空间声明从根节点移动到开始使用该名称空间的子节点。XSLT 1.0将命名空间移动到子节点

源XML:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<Accounts xmlns:test="http:example.com/test1"> 
    <ParentAccount>10113146</ParentAccount> 
    <test1>test1</test1> 
    <test2>test2</test2> 
    <test:Siblings> 
     <test:CustomerNumber>10113146</test:CustomerNumber> 
     <test:CustomerNumber>120051520</test:CustomerNumber> 
    </test:Siblings> 
</Accounts> 

期望中的XML:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<Accounts x> 
    <ParentAccount>10113146</ParentAccount> 
    <test1>test1</test1> 
    <test2>test2</test2> 
    <test:Siblings xmlns:test="http:example.com/test1"> 
     <test:CustomerNumber>10113146</test:CustomerNumber> 
     <test:CustomerNumber>120051520</test:CustomerNumber> 
    </test:Siblings> 
</Accounts> 

什么好主意?

下面介绍一种方法。

当这个XSLT:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<Accounts xmlns:test="http:example.com/test1"> 
    <ParentAccount>10113146</ParentAccount> 
    <test1>test1</test1> 
    <test2>test2</test2> 
    <test:Siblings> 
    <test:CustomerNumber>10113146</test:CustomerNumber> 
    <test:CustomerNumber>120051520</test:CustomerNumber> 
    </test:Siblings> 
</Accounts> 

......想要的结果产生:

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

    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Accounts"> 
    <Accounts> 
     <xsl:apply-templates /> 
    </Accounts> 
    </xsl:template> 

</xsl:stylesheet> 

......是对所提供的XML应用

<?xml version="1.0"?> <Accounts> <ParentAccount>10113146</ParentAccount> <test1>test1</test1> <test2>test2</test2> <test:Siblings xmlns:test="http:example.com/test1"> <test:CustomerNumber>10113146</test:CustomerNumber> <test:CustomerNumber>120051520</test:CustomerNumber> </test:Siblings> </Accounts> 

说明:

背后为什么这个作品的解释与来自Namespaces in XML 1.0规范中的一个部分开始:

空间声明中宣布前缀的范围从 扩展开始标记的开始其中它看起来在相应的结束标记 的末尾,排除具有相同NSAttName部分的任何内部声明 的范围。如果是空标签,范围 就是标签本身。

此类名称空间声明适用于其范围内所有元素和属性 的名称,其前缀与 声明中指定的名称相匹配。

简而言之,这意味着当一个名称空间在一个元素上声明时,它实际上被定义为用于该原始作用域下的所有元素。此外,如果一个名称空间在一个元素上被使用而没有首先在其他地方被定义,那么适当的定义就发生在该元素上。

因此,使用您的文档,我的XSLT,让我们来看看如何发挥出来:

  1. 第一个模板 - The Identity Template - 将所有节点和属性,是从源XML的结果XML。
  2. 第二个模板替换原来的<Accounts>元素;顺便说一句,这个新的<Accounts>元素没有定义http:example.com/test1命名空间。最后,此模板将模板应用于<Accounts>的所有子元素。
  3. 当处理器达到<test:Siblings>时,它会看到一个名称空间,尽管它存在于原始XML中,但仍未在结果文档中正确定义。因此,该定义被添加到<test:Siblings>
+0

Hello ABach,你能解释一下为什么,或者提供解释它的链接吗?我在处理XSLT中的命名空间方面没有经验(我通常首先摆脱它们)。谢谢彼得 – Peter 2013-05-05 19:06:07

+0

@彼得 - 我添加了一个解释。如果您还有其他问题,请告诉我。 – ABach 2013-05-05 21:12:25

+0

@ABACK:谢谢+1 – Peter 2013-05-13 06:59:10