Complex XPath axes/where (BizTalk EDI 856 Schema)



要求是在HL1Loop中找到HL03='P'和HL01='3'的MAN02段的值(在一个可能有几十个HL1Loop的文件中,但我只包括了几个为了重现这个问题。

我得到了这么多工作:

//*[local-name()='HLLoop1'][.//*[HL03='P'] and .//*[HL01='3']]

将返回所需的 HLLoop1(下面是示例数据)。我有理由获取该特定项目,太长了,无法在此处解释(分析表示 856 EDI 提前发货通知文档的 Microsoft BizTalk 架构)。可能还有其他HLLoop1中也有"MAN02",这就是我需要的。

现在我只想返回 MAN02 值。 试过这个,但这是不行的:

//*[local-name()='HLLoop1']//MAN/MAN02[.//*[HL03='P'] and .//*[HL01='3']]

我是否需要添加更多前缀才能让 HL03 返回几个节点,如下所示?

//*[local-name()='HLLoop1']//MAN/MAN02[.//.//.//*[HL03='P'] and .//.//.//*[HL01='3']]

或者我会在最后添加一些东西,如下所示:

//*[local-name()='HLLoop1'][.//*[HL03='P'] and .//*[HL01='3']]//*MAN02

这提供了"额外的非法代币",我认为也许在正确的位置添加更多括号可以解决它。

我知道这是一个让轴和"where子句"直截了当的问题。

这里的例子: http://www.xpathtester.com/xpath/3005df62b369fd0fff86e7b3e492a377

数据

<ns0:X12_00401_856 xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006">
<ns0:HLLoop1>
<ns0:HL>
<HL01>2</HL01>
<HL02>1</HL02>
<HL03>O</HL03>
</ns0:HL>
<ns0:PRF>
<PRF01>287775</PRF01>
</ns0:PRF>
</ns0:HLLoop1>
<ns0:HLLoop1>
<ns0:HL>
<HL01>3</HL01>
<HL02>2</HL02>
<HL03>P</HL03>
</ns0:HL>
<ns0:MAN>
<MAN01>CP</MAN01>
<MAN02>465467995515</MAN02>
</ns0:MAN>
</ns0:HLLoop1>
</ns0:X12_00401_856>

我将使用它 XSLT,如下所示:

<LineItemCarrierTrackingNum>
<xsl:variable name="currentHL02" select="HL02" /> 
<xsl:value-of select="concat("//*[local-name()='HLLoop1'][.//*[HL03='O'] and ..//*[HL01='", $currentHL02,"']]//*MAN02";  /> 
</LineItemCarrierTrackingNum> 

我希望我可以将 XPath 构建为变量,如上所示......

如果您使用的是 XSLT(即使不是),也应避免使用可以选择超出预期内容的/*[local-name()='..'](更不用说不可读了)。另请注意,使用显式路径比后代轴更有效。

请考虑以下样式表:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006"
exclude-result-prefixes="ns0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/ns0:X12_00401_856">
<result>
<xsl:value-of select="ns0:HLLoop1[ns0:HL/HL01='3' and ns0:HL/HL03='P']/ns0:MAN/MAN02"/>
</result>
</xsl:template>
</xsl:stylesheet>

应用于您的输入示例,结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<result>465467995515</result>

您的问题的简单答案是使用表达式//MAN02.

好吧,这可能不是你想要的答案;但如果是这样的话,那是因为你没有解释真正的问题。

使用XPath 从单个输入文档中获取数据通常很简单;当您想要构造一个表达式也可以与其他文档一起使用(即,使用与初始测试用例有某种不同文档的文档)时,就会出现问题。所以你需要解释什么是不变量:你的样本文档的哪些部分是一般文档类的可靠特征,哪些部分是偶然的?如果所有文档都像示例文档一样包含单个 MAN02 元素,那么检索 MAN02 元素就非常容易了。

好的,我想我明白了,但想知道是否有更好的方法。

//*[local-name()='HLLoop1'][//*[HL03='P'] and //*[HL01='3']]//MAN02

这是我在原始问题中的选项之一,但需要//MAN02 而不是//*MAN02。 另一种方式也起作用,但同意它太迟钝的评论:

//*[local-name()='HLLoop1']//MAN02[..//..//*[HL03='P'] and ..//..//*[HL01='3']]

有时,你必须休息一晚,对问题有新的看法。 我以前的尝试存在问题:

1) MAN 有一个命名空间,所以只是跳过了//MAN02

2)我使用的是.//而不是.。(一个点是自我,两个点是父级)。 既然我找到了MAN02,我就要上两个父母(一个家长把mae带回MAN,另一个家长带我回HLLOOP1)。

现在我需要尝试 XSLT 中的变量,看看它是否从那里工作。

相关内容

  • 没有找到相关文章

最新更新