2015-06-18 67 views
0

我可以用For-Each做到這一點,但在Apply_Templates時出現了一些問題。XSLT 1.0 - 多個子節點格式化輸出

XML數據包含不同的子節點,但我想顯示所有子節點及其父母信息。

<orders> 
<order> 
    <customer>1</customer> 
    <items> 
     <item> 
      <name>Widget A</name> 
      <price>10</price> 
      <code>1A</code> 
     </item> 
    </items> 
</order> 
<order> 
    <customer>2</customer> 
    <items> 
     <item> 
      <name>Widget A</name> 
      <price>10</price> 
      <code>1A</code> 
     </item> 
    </items> 
    <items> 
     <item> 
      <name>Widget B</name> 
      <price>20</price> 
      <code>2B</code> 
     </item> 
    </items> 
</order> 
<order> 
    <customer>3</customer> 
    <items> 
     <item> 
      <name>Widget A</name> 
      <price>10</price> 
      <code>1A</code> 
     </item> 
    </items> 
    <items> 
     <item> 
      <name>Widget B</name> 
      <price>10</price> 
      <code>1A</code> 
     </item> 
    </items> 
    <items> 
     <item> 
      <name>Widget C</name> 
      <price>30</price> 
      <code>3C</code> 
     </item> 
    </items> 
</order> 

正如你所看到的,有每個客戶每個訂單的多個項目。我所要的輸出是這樣的:

Customer, Name, Price, Code 
1, Widget A, 10, 1A 
2, Widget A, 10, 1A 
2, Widget B, 20, 2B 
3, Widget A, 10, 1A 
3, Widget B, 20, 2B 
3, Widget C, 30, 3C 

當我申請的模板,我只能得到第一個項目,以顯示而不是其他。如果你認爲我應該發佈我的XSL,讓我知道,但我認爲它應該是簡單的卡住了。我想遠離使用for-each。

+1

是的,請張貼您的XSLT。 –

+1

「我想避免使用for-each。*」爲什麼?你有一個規則的,幾乎平坦的結構,並且幾乎沒有單個模板可以做。使用'xsl:for-each'將是這裏獲勝的方法。 –

回答

1

你可以試試這個方法:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" indent="no"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="/"> 
    <xsl:text>Customer, Name, Price ,Code&#xa;</xsl:text> 
    <xsl:apply-templates select="//item"/> 
    </xsl:template> 

    <xsl:template match="item"> 
    <xsl:value-of select="../../customer"/> 
    <xsl:text>, </xsl:text> 
    <xsl:value-of select="name"/> 
    <xsl:text>, </xsl:text> 
    <xsl:value-of select="price"/> 
    <xsl:text>, </xsl:text> 
    <xsl:value-of select="code"/> 
    <xsl:text>&#xa;</xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 
  • 第一個模板輸出文檔中的根元素和打印頭相匹配。

  • 第二個模板匹配item元素並輸出相應的逗號分隔值。通過這種方式,您可以在輸出文檔中包含每個item的行,而無需使用for-each構造。

+1

這肯定會做+1。 'concat()'函數會使它看起來簡單。 –

+1

這與使用'xsl:for-each'幾乎是一樣的。基於模板的方法會有一個單獨的模板來處理訂單商品。另外,你應該避免使用處理器密集型的'//',並使用已知的顯式路徑選擇項目節點。 –

+0

我被建議儘可能遠離每一個,並且每個人都使用它們。我只是想用apply-templates來解決這個問題。我還沒有完全理解爲什麼對於每個不建議與apply-templates的建議。我會看看這個解決方案,並嘗試使用一些類似的例子。謝謝! –

0

我相信一個真正的基於模板的方法應該是這樣的:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text" encoding="utf-8"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/orders"> 
    <xsl:text>Customer, Name, Price, Code&#10;</xsl:text> 
    <xsl:apply-templates select="order/items/item"/> 
</xsl:template> 

<xsl:template match="item"> 
    <xsl:value-of select="../../customer"/> 
    <xsl:text>, </xsl:text> 
    <xsl:apply-templates/> 
    <xsl:if test="position()!=last()"> 
     <xsl:text>&#10;</xsl:text> 
    </xsl:if> 
</xsl:template> 

<xsl:template match="item/*"> 
    <xsl:value-of select="."/> 
    <xsl:if test="position()!=last()"> 
     <xsl:text>, </xsl:text> 
    </xsl:if> 
</xsl:template> 

</xsl:stylesheet> 

然而,正如我在你的問題的評論中提到,這也是沒有明顯的目的,而不是將代碼分解成難以遵循的不連續塊。