Xml 每个循环的XSLT
我有一个非常棘手的XSLT问题。 假设我有以下输入:Xml 每个循环的XSLT,xml,xslt,Xml,Xslt,我有一个非常棘手的XSLT问题。 假设我有以下输入: <OtherCharges> <LineId> <Id>P</Id> </LineId> <Items> <Item1>1</Item1> <Item2>2</Item2> <Item3>3</Item3> </Items> &l
<OtherCharges>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>1</Item1>
<Item2>2</Item2>
<Item3>3</Item3>
</Items>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>4</Item1>
</Items>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>5</Item1>
<Item2>6</Item2>
</Items>
</OtherCharges>
P
1.
2.
3.
P
4.
P
5.
6.
作为一个输出,我希望有以下内容:
<OtherCharges>
<LineId>P</LineId>
<OtherChargesValues>
<value>1</value>
<value>2</value>
<value>3</value>
</OtherChargesValues>
</OtherCharges>
<OtherCharges>
<LineId>P</LineId>
<OtherChargesValues>
<value>4</value>
</OtherChargesValues>
</OtherCharges>
<OtherCharges>
<LineId>P</LineId>
<OtherChargesValues>
<value>5</value>
<value>6</value>
</OtherChargesValues>
</OtherCharges>
P
1.
2.
3.
P
4.
P
5.
6.
我可以有一个无限的行数,但每行最多有3个项目。
我尝试了以下代码:
<xsl:for-each select="/OtherCharges/LineId">
<Id>
<xsl:value-of select="Id"/>
<Id>
<xsl:variable name="ChargeLine" select="."/>
<xsl:for-each select="following-sibling::Items[preceding-sibling::LineId[1] = $ChargeLine]">
<xsl:if test="name(.)='Items'">
<xsl:if test="Item1">
<value>
<xsl:value-of select="Item1"/>
</value>
</xsl:if>
<xsl:if test="Item2">
<value>
<xsl:value-of select="Item2"/>
</value>
</xsl:if>
<xsl:if test="Item3">
<value>
<xsl:value-of select="Item3"/>
</value>
</xsl:if>
</xsl:if>
</xsl:for-each>
如果ID不同,它工作得很好,但问题是当我有相同的ID值时(如示例中所示)。
有人能帮我吗
谢谢 一般来说,避免usng值并了解应用模板,这将成为一个非常简单的XSLT问题。顺便说一下,您的输出不是格式良好的XML,因为它没有一个根包装器元素
<xsl:strip-space elements="OtherCharges" />
<xsl:template match="OtherCharges">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="OtherCharges/LineId">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="OtherCharges/Items">
<xsl:apply-templates/>
</xsl:template>
<!--* now the real work *-->
<xsl:template match="OtherCharges/LineId/Id">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match="OtherCharges/Items/*">
<value><xsl:apply-templates/></value>
</xsl:template>
开始-使用()
可能有助于
XML输入
<OtherCharges>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>1</Item1>
<Item2>2</Item2>
<Item3>3</Item3>
</Items>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>4</Item1>
</Items>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>5</Item1>
<Item2>6</Item2>
</Items>
</OtherCharges>
P
1.
2.
3.
P
4.
P
5.
6.
XSLT1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Id">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Items/*[starts-with(name(),'Item')]">
<value>
<xsl:apply-templates select="@*|node()"/>
</value>
</xsl:template>
</xsl:stylesheet>
XML输出(格式不正确)
P
1.
2.
3.
P
4.
P
5.
6.
此转换:
<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:key name="kFollowing" match="*[not(self::LineId)]"
use="generate-id(preceding-sibling::LineId[1])"/>
<xsl:template match="LineId">
<OtherCharges>
<LineId><xsl:value-of select="."/></LineId>
<OtherChargesValues>
<xsl:apply-templates mode="inGroup"
select="key('kFollowing', generate-id())"/>
</OtherChargesValues>
</OtherCharges>
</xsl:template>
<xsl:template match="Items/*" mode="inGroup">
<value><xsl:value-of select="."/></value>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
<OtherCharges>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>1</Item1>
<Item2>2</Item2>
<Item3>3</Item3>
</Items>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>4</Item1>
</Items>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>5</Item1>
<Item2>6</Item2>
</Items>
</OtherCharges>
应用于提供的XML文档时:
<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:key name="kFollowing" match="*[not(self::LineId)]"
use="generate-id(preceding-sibling::LineId[1])"/>
<xsl:template match="LineId">
<OtherCharges>
<LineId><xsl:value-of select="."/></LineId>
<OtherChargesValues>
<xsl:apply-templates mode="inGroup"
select="key('kFollowing', generate-id())"/>
</OtherChargesValues>
</OtherCharges>
</xsl:template>
<xsl:template match="Items/*" mode="inGroup">
<value><xsl:value-of select="."/></value>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
<OtherCharges>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>1</Item1>
<Item2>2</Item2>
<Item3>3</Item3>
</Items>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>4</Item1>
</Items>
<LineId>
<Id>P</Id>
</LineId>
<Items>
<Item1>5</Item1>
<Item2>6</Item2>
</Items>
</OtherCharges>
P
1.
2.
3.
P
4.
P
5.
6.
生成所需的正确结果:
<OtherCharges>
<LineId>P</LineId>
<OtherChargesValues>
<value>1</value>
<value>2</value>
<value>3</value>
</OtherChargesValues>
</OtherCharges>
<OtherCharges>
<LineId>P</LineId>
<OtherChargesValues>
<value>4</value>
</OtherChargesValues>
</OtherCharges>
<OtherCharges>
<LineId>P</LineId>
<OtherChargesValues>
<value>5</value>
<value>6</value>
</OtherChargesValues>
</OtherCharges>
P
1.
2.
3.
P
4.
P
5.
6.
它不会产生问题中所要求的输出:元素应该被称为值
,而不是项1
,项2
等。@MiMo-我没有注意到这一点。接得好。我会在有时间时尝试更新。谢谢谢谢你的回答,但是输出是错误的。对此我非常抱歉。我已经编辑了输出。注意:谢谢您的回答,但输出是错误的。对此我非常抱歉。事实上,它似乎有一个简单的解决方案,但我不是很有经验。谢谢。谢谢你的回答,但是输出是错误的。对此我非常抱歉。我已经编辑了输出。效果很好!我实际上不知道generate-id()。谢谢。“…是在XSLT 1.0中测试节点标识的唯一方法”@user295744,不客气。generate-id()是在XSLT1.0中测试节点标识的唯一方法。在XPath 2.0(XSLT 2.0)中,存在is运算符,其唯一语义是确认两个节点之间的标识@MiMo,谢谢你注意到这一点。注释中的输入错误现在已修复。@user295744,实际上,在XPath 1.0中检查节点标识至少还有一种方法:count($n1 |$n2)=1