我需要使用Xpath1.0在XML中迭代2个级别的嵌套循环。
迭代时,如果它是第二级的第一个元素,当前索引作为计数器,它应该打印元素值'Y'。
我能够完成其中一件事,但不能同时完成两件事。 例如如果我迭代第一个循环并使用position()它给我当前索引,但我无法识别它是否是第二级的第一个元素。类似地,如果我迭代第二个循环,我不会获得实际索引,但如果它是第一个元素使用position()= 1
我附上了样本请求和预期回复。
<root>
<level1>
<level2>name1</level2>
<level2>name2</level2>
</level1>
<level1>
<level2>name3</level2>
<level2>name4</level2>
<level2>name5</level2>
</level1>
<level1>
<level2>name6</level2>
<level2>name7</level2>
</level1>
</root>
结果应该是这样的:
name1_Y_1
name2_N_2
name3_Y_3
name4_N_4
name5_N_5
name6_Y_6
name7_N_7
以下是现有代码:
<root>
<xsl:for-each select="$Map-Data/root/level1/level2">
<xsl:choose>
<xsl:when test="position() = 1">
<names>
<xsl:value-of select="concat(current(), '_Y_', position())"/>
</names>
</xsl:when>
<xsl:otherwise>
<names>
<xsl:value-of select="concat(current(), '_N_', position())"/>
</names>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</root>
答案 0 :(得分:1)
使用XPath 2.0,你可以做到
//level2/concat(., if (not(preceding-sibling::*)) then '_Y' else '_N', '_', position())
使用XPath 1.0时,您需要确保在迭代preceding-sibling::*
时检查//level2
并使用您的宿主语言进行字符串连接。
正如你现在展示的样本使用XSLT我会做
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="root">
<xsl:copy>
<!-- <xsl:apply-templates select="$Map-Data/root/level1/level2"/> -->
<xsl:apply-templates select="level1/level2"/>
</xsl:copy>
</xsl:template>
<xsl:template match="level2[not(preceding-sibling::*)]">
<names>
<xsl:value-of select="concat(., '_Y_', position())"/>
</names>
</xsl:template>
<xsl:template match="level2[preceding-sibling::*]">
<names>
<xsl:value-of select="concat(., '_N_', position())"/>
</names>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
您的方法不起作用的原因在于选择:
<xsl:for-each select="/root/level1/level2">
您选择所有 level2
元素作为单个节点集 - 并且整个集合中只有一个成员可以位于#1位置。
OTOH,如果你要像这样分开你的选择:
<xsl:for-each select="/root/level1">
<xsl:for-each select="level2">
<xsl:choose>
<xsl:when test="position() = 1">
<names>
<xsl:value-of select="concat(current(), '_Y_', position())"/>
</names>
</xsl:when>
<xsl:otherwise>
<names>
<xsl:value-of select="concat(current(), '_N_', position())"/>
</names>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
您将为每个level1
元素处理单独的节点集,从而实现在每个批次中位置#1处具有单独level2
元素的目标。
但是,您不能使用相同的position()函数连续对所有元素进行编号,因为它会在每次level1
更改时重新启动(这就是您使Y / N工作的方式)。为此,您必须使用其他编号机制,例如xsl:number
:
<xsl:for-each select="root/level1">
<xsl:for-each select="level2">
<names>
<xsl:value-of select="."/>
<xsl:choose>
<xsl:when test="position() = 1">_Y_</xsl:when>
<xsl:otherwise>_N_</xsl:otherwise>
</xsl:choose>
<xsl:number level="any"/>
</names>
</xsl:for-each>
</xsl:for-each>