2016-10-25 19 views
1

我遇到了XSLT和for-each的问题。所有迭代的值似乎都会被检索并分配给每次迭代的特定节点。XSLT循环 - 分配给每个特定节点的所有迭代中的值

XML

<TABLE> 
 
    <HEADER xmlns=""> 
 
     <DETAIL xmlns=""> 
 
     <value1 xmlns="">value1</value1> 
 
     <value2 xmlns="">value2</value2> 
 
     </DETAIL> 
 
\t <DETAIL xmlns=""> 
 
     <value1 xmlns="">value3</value1> 
 
     <value2 xmlns="">value4</value2> 
 
     </DETAIL> 
 
    </HEADER> 
 
</TABLE>

XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"> 
 
    <xsl:template match="*"> 
 
     <xsl:element name="Json"> 
 
      <xsl:for-each select="*:HEADER/*:DETAIL"> 
 
       <xsl:element name="array"> 
 
        <xsl:element name="test1"><xsl:value-of select="../../*:HEADER/*:DETAIL/*:value1"/></xsl:element> 
 
        <xsl:element name="test2"><xsl:value-of select="../../*:HEADER/*:DETAIL/*:value2"/></xsl:element> 
 
       </xsl:element> 
 
      </xsl:for-each> 
 
     </xsl:element> 
 
    </xsl:template> 
 
</xsl:stylesheet>

这是输出我得到:

实际

<?xml version="1.0" encoding="UTF-8"?> 
 
<Json> 
 
\t <array> 
 
\t \t <test1>value1 value3</test1> 
 
\t \t <test2>value2 value4</test2> 
 
\t </array> 
 
\t <array> 
 
\t \t <test1>value1 value3</test1> 
 
\t \t <test2>value2 value4</test2> 
 
\t </array> 
 
</Json>

预计

<?xml version="1.0" encoding="UTF-8"?> 
 
<Json> 
 
\t <array> 
 
\t \t <test1>value1</test1> 
 
\t \t <test2>value2</test2> 
 
\t </array> 
 
\t <array> 
 
\t \t <test1>value3</test1> 
 
\t \t <test2>value4</test2> 
 
\t </array> 
 
</Json>

回答

0

你需要改变这一部分:

<xsl:element name="test1"><xsl:value-of select="../../*:HEADER/*:DETAIL/*:value1"/></xsl:element> 
<xsl:element name="test2"><xsl:value-of select="../../*:HEADER/*:DETAIL/*:value2"/></xsl:element> 

到:

<xsl:element name="test1"><xsl:value-of select="*:value1"/></xsl:element> 
<xsl:element name="test2"><xsl:value-of select="*:value2"/></xsl:element> 

你现在有什么上升到祖先TABLE并选择所有value1value2后裔。


注意

  1. xsl:element当元素的名称需要 计算应该被使用。在你的情况下,你可以使用文字结果元素,例如 来简化样式表。

    <test1><xsl:value-of select="*:value1"/></test1> 
    <test2><xsl:value-of select="*:value2"/></test2> 
    
  2. 使用通配符作为命名空间前缀可能导致不可预知的结果;您应该将这种做法限制在传入XML的名称空间未知的极少数情况下。
0

下面是一个完整/短溶液

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

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

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

    <xsl:template match="DETAIL/*"> 
    <xsl:element name="test{position()}"><xsl:apply-templates/></xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

当所提供的XML文档施加:

<TABLE> 
    <HEADER xmlns=""> 
     <DETAIL xmlns=""> 
      <value1 xmlns="">value1</value1> 
      <value2 xmlns="">value2</value2> 
     </DETAIL> 
     <DETAIL xmlns=""> 
      <value1 xmlns="">value3</value1> 
      <value2 xmlns="">value4</value2> 
     </DETAIL> 
    </HEADER> 
</TABLE> 

有用,正确的结果产生

<Json> 
    <array> 
     <test1>value1</test1> 
     <test2>value2</test2> 
    </array> 
    <array> 
     <test1>value3</test1> 
     <test2>value4</test2> 
    </array> 
</Json> 

请注意

  1. 没有<xsl:for-each>使用 - 实际上存在XSLT几乎没有任何场景<xsl:for-each>是必要的。使用模板会产生更强大/多态/灵活和可重用的解决方案。根据需要

  2. 源XML文档可以有各DETAIL元件作为许多孩子,(以及每个DETAIL元件可以具有其自身的,不同数量的儿童)和转化中的结果产生正确的元素名称(test{N}) 。

享受! :)