2016-10-25 30 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}) 。

享受! :)