如何在XSLT中选取packagingLevel为当前值减1的前置兄弟节点?
XSLT查找对应层级前置兄弟节点的TYPE_UE值问题
我是XSLT新手,做了相关研究后仍无法解决问题,特此求助。
我的XML结构中,每个units/results元素包含packagingLevel子节点。我需要找到当前节点的前置兄弟节点,其packagingLevel值等于当前节点的packagingLevel值减1,并获取该节点对应的转换后TYPE_UE值。例如当前节点packagingLevel为5时,找packagingLevel为4的兄弟节点对应的TYPE_UE。
输入XML示例
<root> <header> <products> <results> <units> <results> <itemCode>001</itemCode> <packagingType>BOX</packagingType> <eanCode>0000000000001</eanCode> <packagingLevel>1</packagingLevel> <quantity>1</quantity> </results> <results> <itemCode>002</itemCode> <packagingType>PALETTE</packagingType> <eanCode>0000000000002</eanCode> <packagingLevel>2</packagingLevel> <quantity>1</quantity> </results> </units> </results> </products> </header> </root>
尝试的XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="yes" /> <xsl:template match="/"> <xsl:for-each select="//products/results"> <Element> <xsl:for-each select="units/results"> <UE> <UE_EAN> <xsl:value-of select="eanCode" /> </UE_EAN> <TYPE_UE> <xsl:choose> <xsl:when test="packagingLevel = 1">A01</xsl:when> <xsl:when test="packagingType = 'BOX'">B01</xsl:when> <xsl:when test="packagingType = 'PALETTE'">P01</xsl:when> </xsl:choose> </TYPE_UE> <TYPE_UE_CONTENT> <xsl:choose> <xsl:when test="packagingLevel = 1">A01</xsl:when> <xsl:otherwise> <xsl:variable name="prevLevel" select="preceding-sibling::units[packagingLevel = current()/packagingLevel - 1]/TYPE_UE" /> <xsl:value-of select="$prevLevel"/> </xsl:otherwise> </xsl:choose> </TYPE_UE_CONTENT> <UE_QTE> <xsl:value-of select="quantite" /> </UE_QTE> </UE> </xsl:for-each> </Element> </xsl:for-each> </xsl:template> </xsl:stylesheet>
当前输出
<Element> <... /> <... /> <UE> <UE_EAN>0000000000001</UE_EAN> <TYPE_UE>A01</TYPE_UE> <TYPE_UE_CONTENT>A01</TYPE_UE_CONTENT> <UE_QTY>1</UE_QTY> </UE> <UE> <UE_EAN>0000000000002</UE_EAN> <TYPE_UE>P01</TYPE_UE> <TYPE_UE_CONTENT /> <UE_QTE>2</UE_QTE> </UE> <... /> </Element>
期望输出
<Element> <... /> <... /> <UE> <UE_EAN>0000000000001</UE_EAN> <TYPE_UE>A01</TYPE_UE> <TYPE_UE_CONTENT>A01</TYPE_UE_CONTENT> <UE_QTY>1</UE_QTY> </UE> <UE> <UE_EAN>0000000000002</UE_EAN> <TYPE_UE>P01</TYPE_UE> <TYPE_UE_CONTENT>A01</TYPE_UE_CONTENT> <UE_QTE>2</UE_QTE> </UE> <... /> </Element>
问题分析与修正方案
你的代码存在三个关键问题:
- 前置兄弟节点选择错误:当前节点是
units/results,其兄弟节点是同层级的results,而非units,所以应该用preceding-sibling::results而非preceding-sibling::units。 - 无法直接引用转换后的
TYPE_UE元素:TYPE_UE是你转换生成的节点,原XML中不存在,需要对找到的前置兄弟节点重新计算对应的TYPE_UE值。 - 拼写错误:原XML中是
quantity,你代码里写的是quantite,导致UE_QTE值为空。
修正后的XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="yes" /> <!-- 定义复用的TYPE_UE计算模板,避免重复代码 --> <xsl:template name="get-type-ue"> <xsl:param name="node"/> <xsl:choose> <xsl:when test="$node/packagingLevel = 1">A01</xsl:when> <xsl:when test="$node/packagingType = 'BOX'">B01</xsl:when> <xsl:when test="$node/packagingType = 'PALETTE'">P01</xsl:when> </xsl:choose> </xsl:template> <xsl:template match="/"> <xsl:for-each select="//products/results"> <Element> <xsl:for-each select="units/results"> <UE> <UE_EAN> <xsl:value-of select="eanCode" /> </UE_EAN> <TYPE_UE> <xsl:call-template name="get-type-ue"> <xsl:with-param name="node" select="."/> </xsl:call-template> </TYPE_UE> <TYPE_UE_CONTENT> <xsl:choose> <xsl:when test="packagingLevel = 1">A01</xsl:when> <xsl:otherwise> <!-- 找到packagingLevel为当前层级-1的前置兄弟节点 --> <xsl:variable name="prev-sibling" select="preceding-sibling::results[packagingLevel = current()/packagingLevel - 1]"/> <!-- 调用模板计算对应的TYPE_UE值 --> <xsl:call-template name="get-type-ue"> <xsl:with-param name="node" select="$prev-sibling"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </TYPE_UE_CONTENT> <UE_QTE> <xsl:value-of select="quantity" /> </UE_QTE> </UE> </xsl:for-each> </Element> </xsl:for-each> </xsl:template> </xsl:stylesheet>
修正说明
- 新增
get-type-ue模板,复用TYPE_UE的计算逻辑,避免重复代码,同时保证前置兄弟节点的TYPE_UE计算和当前节点一致。 - 修正前置兄弟节点的选择表达式,正确定位到同层级的
results节点。 - 修复
quantity的拼写错误,确保UE_QTE能正确取值。
运行修正后的代码即可得到你期望的输出。
内容的提问来源于stack exchange,提问作者Ollysheep
相关产品推荐
相关产品推荐

