XSLT foreach循环
我在过去的几周里只介绍过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() > 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>
伍迪,再次感谢,你。这真棒。
与您问题的关键是,你无法通过数据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() > 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 =。)])
感谢您的帮助。要回答你的问题,我会在我原来的帖子中添加一些额外的信息。 –
再次感谢您。你可以用例子展开最后一节
我的意思是,因为一旦你确定了你有哪些独特的元素,你必须把它们放在每个中,你必须做3次测试,每次td一次,因为没有办法存储这个值,为了打印价值观而着手。所以,即使你做了一个测试,发现ZZZ是存在的,并且你知道所有tds的所有3个值,你必须在开始第二个td之前完成第一个td。我现在还没有机会写下来,如果你仍然需要,可以在几个小时内完成。 – Woody
您忘记指定进入单元格E,F,G,H和I的内容。请*编辑*问题并提供缺少的信息。 –