xslt 中的 For-Each 问题
Issue with For-Each in xslt
鉴于 xml:
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<Interchange>
<Group>
<Message>
<Loop2000>
<Loop2300>
<K3>
<F449>BlaBlaBla</F449>
</K3>
<K3>
<F449>IEHPTraceID_123456</F449>
</K3>
</Loop2300>
</Loop2000>
</Message>
</Group>
</Interchange>
</Envelope>
和以下 xslt:
<xsl:transform 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="Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3">
<xsl:if test="substring(/Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3/F449,1,11)='IEHPTraceID'">
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue><xsl:value-of select="/Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3/F449" /></AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:transform>
我期待的结果是:
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue>IEHPTraceID_123456</AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
显然我的 for-each 有问题,因为我假设它会看到正确的节点并输出预期的结果,但那并没有发生。如果我删除第一个节点,我会得到预期的结果。有人可以引导我朝着正确的方向前进吗
请尝试以下 XSLT。
在xsl:for-each
循环中,上下文是K3元素的所有子节点。无需在 XPath 表达式中再次从根开始。
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:for-each select="Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3">
<xsl:if test="substring(F449,1,11)='IEHPTraceID'">
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue>
<xsl:value-of select="F449"/>
</AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
输出
<?xml version='1.0' ?>
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue>IEHPTraceID_123456</AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
使用时使用 xsl:for - 每个上下文都会更改为所选元素。所以在循环内部,上下文是 K3 和 child-element F449。所以你可以像这样直接测试 child:
<xsl:transform 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="Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3">
<xsl:if test="substring(F449,1,11)='IEHPTraceID'">
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue><xsl:value-of select="F449" /></AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:transform>
您可以通过使用谓词而不使用 xsl:if 来获得相同的效果,如下所示:
<xsl:transform 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="Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3[substring(F449,1,11)='IEHPTraceID']">
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue><xsl:value-of select="F449" /></AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
</xsl:for-each>
</xsl:template>
</xsl:transform>
作为 xsl:foreach 的替代方案,您也可以这样做:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="K3"/>
<xsl:template match="K3[substring(F449,1,11)='IEHPTraceID']">
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue><xsl:value-of select="F449" /></AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
</xsl:template>
</xsl:transform>
鉴于 xml:
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<Interchange>
<Group>
<Message>
<Loop2000>
<Loop2300>
<K3>
<F449>BlaBlaBla</F449>
</K3>
<K3>
<F449>IEHPTraceID_123456</F449>
</K3>
</Loop2300>
</Loop2000>
</Message>
</Group>
</Interchange>
</Envelope>
和以下 xslt:
<xsl:transform 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="Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3">
<xsl:if test="substring(/Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3/F449,1,11)='IEHPTraceID'">
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue><xsl:value-of select="/Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3/F449" /></AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:transform>
我期待的结果是:
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue>IEHPTraceID_123456</AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
显然我的 for-each 有问题,因为我假设它会看到正确的节点并输出预期的结果,但那并没有发生。如果我删除第一个节点,我会得到预期的结果。有人可以引导我朝着正确的方向前进吗
请尝试以下 XSLT。
在xsl:for-each
循环中,上下文是K3元素的所有子节点。无需在 XPath 表达式中再次从根开始。
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:for-each select="Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3">
<xsl:if test="substring(F449,1,11)='IEHPTraceID'">
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue>
<xsl:value-of select="F449"/>
</AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
输出
<?xml version='1.0' ?>
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue>IEHPTraceID_123456</AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
使用时使用 xsl:for - 每个上下文都会更改为所选元素。所以在循环内部,上下文是 K3 和 child-element F449。所以你可以像这样直接测试 child:
<xsl:transform 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="Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3">
<xsl:if test="substring(F449,1,11)='IEHPTraceID'">
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue><xsl:value-of select="F449" /></AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:transform>
您可以通过使用谓词而不使用 xsl:if 来获得相同的效果,如下所示:
<xsl:transform 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="Envelope/Interchange/Group/Message/Loop2000/Loop2300/K3[substring(F449,1,11)='IEHPTraceID']">
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue><xsl:value-of select="F449" /></AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
</xsl:for-each>
</xsl:template>
</xsl:transform>
作为 xsl:foreach 的替代方案,您也可以这样做:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="K3"/>
<xsl:template match="K3[substring(F449,1,11)='IEHPTraceID']">
<InboundDataXml>
<CustomAttributes>
<CustomAttribute>
<AttributeName>Trace Id</AttributeName>
<AttributeValue><xsl:value-of select="F449" /></AttributeValue>
</CustomAttribute>
</CustomAttributes>
</InboundDataXml>
</xsl:template>
</xsl:transform>