2012-06-07 138 views
0

我在過去的幾周裏只介紹過xslt和xml,我迫切需要一些幫助來編寫一些代碼來實現我想實現的目標。 我有以下XML:XSLT foreach循環

<?xml version="1.0" encoding="UTF-8"?> 
<abc1 formName="Form"> 
    <Level1> 
     <Element1>ZZZ</Element1> 
     <Element2> 
      <SubElement1>Apples</SubElement1> 
      <SubElement2>Oranges</SubElement2> 
      <SubElement3>Pears</SubElement3> 
      <SubElement4>Blueberries</SubElement4> 
      <SubElement5>Milkshakes</SubElement5> 
     </Element2> 
    </Level1> 
    <Level1> 
     <Element1>XXX</Element1> 
     <Element2> 
      <SubElement1>Apples</SubElement1> 
      <SubElement2>Oranges</SubElement2> 
      <SubElement3>Kiwifruit</SubElement3> 
      <SubElement4>Blueberries</SubElement4> 
      <SubElement5>Soda</SubElement5> 
     </Element2> 
    </Level1> 
</abc1> 

和下面的HTML表:

<table> 
<tr> 
    <td width="180" > Row 1</td> 
    <td width="540" colspan="4"> Cell_A</td> 
</tr> 
<tr> 
    <td width="180" >Types</td> 
    <td width="180" >Type 1</td> 
    <td width="180" >Type 2</td> 
    <td width="180" >Type 3</td> 
</tr> 
<tr> 
    <td width="180" >Row 2</td> 
    <td width="180" >Cell_B</td> 
    <td width="180" >Cell_C</td> 
    <td width="180" >Cell_D</td> 
</tr> 
<tr> 
    <td width="180" > Row 3</td> 
    <td width="180" >Cell_E</td> 
    <td width="180" >Cell_F</td> 
    <td width="180" >Cell_G</td> 
</tr> 
<tr> 
    <td width="180" >Row 4</td> 
    <td width="180" >Cell_H</td> 
    <td width="180" >Cell_I</td> 
    <td width="180" >Cell_J</td> 
</tr> 
<tr> 
    <td width="180" > Row 5</td> 
    <td width="540" colspan="4"> Cell_K</td> 
</tr> 
</table> 

我使用XSLT從XML數據提取到表,因爲規則,我需要有麻煩申請使其非常複雜。以下是需要應用於我遇到麻煩的單元格的規則。

(1)如果<Element1>值是在整個XML,則相同的:

如果<Element1> = 'ZZZ' 然後Cell_B = '10',Cell_C = '20',和Cell_D = '30'

如果<Element1> = 'XXX' 然後Cell_B = '100',Cell_C = '90',和Cell_D = '80'

但如果<Element1>值不同在XML,則:

Cell_B = '10,100',Cell_C = '20,90'和Cell_D = '30,80'

(2)如果<SubElement5>值是在整個XML,則相同的:

Cell_J =的<SubElement5>

值,但如果<SubElement5>值在XML不同,則:

Cell_J =用逗號分隔的<SubElement5>值的值

所以在這種情況下,Cell_J的值將是'奶昔蘇打'。

我一直在嘗試用不同的東西:

<xsl:for-each select="./Level1/Element2"> 
<xsl:value-of select="./SubElement5"/> 
</xsl:for-each> 

,但我不能確定我可以使用什麼樣的代碼來檢查,如果它們是相同的,因爲我不能覆蓋變量的值。

編輯: 請注意,我在前面已經指出的小區(小區B,C,d,和j)是唯一我 需要幫助。另外,對於Element1,我可能遇到四個潛在值:012 ZXZ,XXX,AAA和BBB。所需的值對於每個這些將是: (小區B,C,和d)

ZZZ:10,20,30 
XXX:100,90,80 
AAA:40,30,30 
BBB:50,30,20 

所以如果只有一個在整個XML潛在價值,所述細胞應出現如上述的值。如果兩個元素1的值不同,則單元格應在每個單元格中列出上述值,並用逗號分隔。

對於cell_j,我會嘗試解釋它好一點。

首先,我需要確定整個xml中<SubElement5>是否是相同的值。在這種情況下,它不是,在一個部分是奶昔,另一部分是'蘇打'。因此,cell_J應該包含文字'奶昔,蘇打'。

如果XML是這樣的:

<?xml version="1.0" encoding="UTF-8"?> 
    <abc1 formName="Form"> 
     <Level1> 
      <Element1>ZZZ</Element1> 
      <Element2> 
       <SubElement1>Apples</SubElement1> 
       <SubElement2>Oranges</SubElement2> 
       <SubElement3>Pears</SubElement3> 
       <SubElement4>Blueberries</SubElement4> 
       <SubElement5>Milkshakes</SubElement5> 
      </Element2> 
     </Level1> 
     <Level1> 
      <Element1>XXX</Element1> 
      <Element2> 
       <SubElement1>Apples</SubElement1> 
       <SubElement2>Oranges</SubElement2> 
       <SubElement3>Kiwifruit</SubElement3> 
       <SubElement4>Blueberries</SubElement4> 
       <SubElement5>Milkshakes</SubElement5> 
      </Element2> 
     </Level1> 
    </abc1> 

那麼對於cell_j值也只是 '奶昔'。

在此先感謝任何人誰可以提供幫助。

這個問題的答案:

總結一下伍迪下面沒有爲任何人的將來參考:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="/abc1"> 
      <xsl:variable name="elements" select="//Element1[not(preceding::Element1 = .)]"/> 
<table> 
<tr> 
    <td width="180" > Row 1</td> 
    <td width="540" colspan="4"> Cell_A</td> 
</tr> 
<tr> 
    <td width="180" >Types</td> 
    <td width="180" >Type 1</td> 
    <td width="180" >Type 2</td> 
    <td width="180" >Type 3</td> 
</tr> 
<tr> 
    <td width="180" >Row 2</td> 
    <td width="180" > <xsl:for-each select="$elements"> 
      <xsl:if test="position() != 1">,</xsl:if> 
      <xsl:choose> 
       <xsl:when test=". = 'AAA'">40</xsl:when> 
       <xsl:when test=". = 'BBB'">50</xsl:when> 
       <xsl:when test=". = 'XXX'">100</xsl:when> 
       <xsl:when test=". = 'ZZZ'">10</xsl:when> 
      </xsl:choose> 
     </xsl:for-each></td> 
    <td width="180" ><xsl:for-each select="$elements"> 
      <xsl:if test="position() != 1">,</xsl:if> 
      <xsl:choose> 
       <xsl:when test=". = 'AAA'">30</xsl:when> 
       <xsl:when test=". = 'BBB'">30</xsl:when> 
       <xsl:when test=". = 'XXX'">90</xsl:when> 
       <xsl:when test=". = 'ZZZ'">20</xsl:when> 
      </xsl:choose> 
     </xsl:for-each></td> 
    <td width="180" ><xsl:for-each select="$elements"> 
      <xsl:if test="position() != 1">,</xsl:if> 
      <xsl:choose> 
       <xsl:when test=". = 'AAA'">30</xsl:when> 
       <xsl:when test=". = 'BBB'">20</xsl:when> 
       <xsl:when test=". = 'XXX'">80</xsl:when> 
       <xsl:when test=". = 'ZZZ'">30</xsl:when> 
      </xsl:choose> 
     </xsl:for-each></td> 
</tr> 
<tr> 
    <td width="180" > Row 3</td> 
    <td width="180" >Cell_E</td> 
    <td width="180" >Cell_F</td> 
    <td width="180" >Cell_G</td> 
</tr> 
<tr> 
    <td width="180" >Row 4</td> 
    <td width="180" >Cell_H</td> 
    <td width="180" >Cell_I</td> 
    <td width="180" ><xsl:for-each select="//SubElement5[not(preceding::SubElement5/text() = text())]"> 
     <xsl:if test="position() &gt; 1">, </xsl:if> 
     <xsl:value-of select="."/> 
    </xsl:for-each></td> 
</tr> 
<tr> 
    <td width="180" > Row 5</td> 
    <td width="540" colspan="4"> Cell_K</td> 
</tr> 
</table> 
     </xsl:template> 
    </xsl:stylesheet> 

伍迪,再次感謝,你。這真棒。

+0

您忘記指定進入單元格E,F,G,H和I的內容。請*編輯*問題並提供缺少的信息。 –

回答

2

與您問題的關鍵是,你無法通過數據itterate得到你想要的東西,因爲你想要的答案是固定的,即如果此,輸出的是,如果這等輸出。因此,您需要一次完成每個部分。

是否有永遠只能2 Level1s?

 <xsl:template match="/abc1"> 
      <table> 
       <tr> 
        <td width="180" >Row 2</td> 
      <xsl:choose> 
       <xsl:when test="not(Level1/Element1='XXX')"> 
        <!-- only ZZZ --> 
         <td width="180" >10</td> 
         <td width="180" >20</td> 
         <td width="180" >30</td> 
       </xsl:when> 
       <xsl:when test="not(Level1/Element1='ZZZ')"> 
        <!-- only YYY --> 
         <td width="180" >100</td> 
         <td width="180" >90</td> 
         <td width="180" >80</td> 
       </xsl:when> 
       <xsl:otherwise> 
        <!-- some combination --> 
         <td width="180" >10,100</td> 
         <td width="180" >20,90</td> 
         <td width="180" >30,80</td> 
       </xsl:otherwise> 
       </xsl:choose> 
       </tr> 
       .. continued 
      </table> 
     </xsl:template> 
    </xsl:stylesheet> 

等每部分。如果你有一個行數,你想他們,那麼逗號分隔,你需要做的每節 或者如果你必須把一個逗號列表中每個部分。

對不起,我看不出有什麼你試圖用cell_j做,似乎沒有成爲其他的人

修改規則:但是,如果你有很多的項目,而不僅僅是2,你需要一個逗號分隔的列表,你可以使用XPath做,所以:再次

<tr> 
    <td> 
    <xsl:for-each select="//SubElement5[not(preceding::SubElement5/text() = text())]"> 
     <xsl:if test="position() &gt; 1">, </xsl:if> 
     <xsl:value-of select="."/> 
    </xsl:for-each> 
    </td> 
    .. maybe other rows the same 
</tr> 

編輯:

所以有關cell_j更新的問題,上面用正確的來了值。

對於第一部分的更新,這將是可能做到對同一主題的變化,如果你想顯示的所有值(所以有4個值,如果你有所有的4個選項)。不幸的是,你已經訂好每一個值,你必須通過一個一個做各,你需要做一個大的部分,所以在一個循環:

<xsl:for-each select="//Element1[not(preceding::Element1/text() = text())]"> 

這將使你在爲一個循環每個唯一的條目,然後根據該值是否爲XXX,ZZZ等來選擇元素

再次編輯

有做你想做的第一部分,包括遞歸函數,外部文檔,並使用各種不同的XSLT implimentations的節點集函數的幾種方式,但作爲一個完全通用容易看不到出路,這是稍微羅嗦,但是很容易看到的版本(我希望):

<xsl:variable name="elements" select="//Element1[not(preceding::Element1 = .)]"/> 
<table> 
    <tr> 
     <td width="180" >Row 2</td> 
    <td> 
     <xsl:for-each select="$elements"> 
      <xsl:if test="position() != 1">,</xsl:if> 
      <xsl:choose> 
       <xsl:when test=". = 'AAA'">40</xsl:when> 
       <xsl:when test=". = 'BBB'">50</xsl:when> 
       <xsl:when test=". = 'XXX'">100</xsl:when> 
       <xsl:when test=". = 'ZZZ'">10</xsl:when> 
      </xsl:choose> 
     </xsl:for-each> 
    </td> 
    <td> 
     <xsl:for-each select="$elements"> 
      <xsl:if test="position() != 1">,</xsl:if> 
      <xsl:choose> 
       <xsl:when test=". = 'AAA'">30</xsl:when> 
       <xsl:when test=". = 'BBB'">30</xsl:when> 
       <xsl:when test=". = 'XXX'">90</xsl:when> 
       <xsl:when test=". = 'ZZZ'">20</xsl:when> 
      </xsl:choose> 
     </xsl:for-each> 
    </td> 
    <td> 
     <xsl:for-each select="$elements"> 
      <xsl:if test="position() != 1">,</xsl:if> 
      <xsl:choose> 
       <xsl:when test=". = 'AAA'">30</xsl:when> 
       <xsl:when test=". = 'BBB'">20</xsl:when> 
       <xsl:when test=". = 'XXX'">80</xsl:when> 
       <xsl:when test=". = 'ZZZ'">30</xsl:when> 
      </xsl:choose> 
     </xsl:for-each> 
    </td> 
    </tr> 
</table> 

其實 - 我不知道,如果一個變量的迭代($在這種情況下,元素)是標準的,它可能是一個撒克遜和msxsl的事情,但如果不是,你可以用它的值替換它(// Element1 [not(preceding :: Element1 =。)])

+0

感謝您的幫助。要回答你的問題,我會在我原來的帖子中添加一些額外的信息。 –

+0

再次感謝您。你可以用例子展開最後一節>我不太清楚你的意思。 –

+0

我的意思是,因爲一旦你確定了你有哪些獨特的元素,你必須把它們放在每個​​中,你必須做3次測試,每次td一次,因爲沒有辦法存儲這個值,爲了打印價值觀而着手。所以,即使你做了一個測試,發現ZZZ是存在的,並且你知道所有tds的所有3個值,你必須在開始第二個td之前完成第一個td。我現在還沒有機會寫下來,如果你仍然需要,可以在幾個小時內完成。 – Woody