【问题标题】:Complex XPath axes/where (BizTalk EDI 856 Schema)复杂 XPath 轴/位置(BizTalk EDI 856 架构)
【发布时间】:2019-09-18 12:27:26
【问题描述】:

要求是在具有 HL03='P' 和 HL01='3' 的 HL1Loop 中找到 MAN02 段的值(在一个可能有数十个 HL1Loops 的文件中,但出于目的,我只包含了几个复制问题。)

我做了这么多工作:

//*[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 构建为变量,如上所示...

【问题讨论】:

    标签: xpath xslt-1.0


    【解决方案1】:

    如果您正在使用 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>
    

    【讨论】:

    • 谢谢,我刚刚发布了我的替代解决方案。即将在 XSLT 中尝试,但 HL02 的值将是一个变量 - 基于我当前在更大的 for-each 中循环通过 xml 的位置。
    • 我看不出HL02 的值在哪里起作用。
    • 看我对 Michael Kay 的回复,现实世界的应用程序显然要困难得多......我在
    • 我只能回答你问的问题。如果您处于不同的上下文中,那么问题就完全不同了——还要注意,如果您只处理ns0:HL/HL03='I'HLLoop1 节点,那么谓词ns0:HL/HL03='P' 永远不会为真。
    【解决方案2】:

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

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

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

    【讨论】:

    • 我正在为 EDI 856 文档使用 Microsoft BizTalk 架构。 HLLoop1 允许包裹内的包裹(例如包裹、托盘、轨道车等),需要一页来解释。所以我在 HL1Loops 中循环,其中 HL03 = "I" - 行项目,我需要返回层次结构以获取相应的 HL1Loop。我在我的 XSLT 片段中提到了这一点,我想使用我当前的 HL02 值来查找相应的 HL01。
    • 恐怕您不能指望我们通过向我们展示不符合要求的代码来解决您的要求。
    • 我不是要求审查需求。要求是在具有 HL03='P' 和 HL01='3' 的 HL1Loop 中找到 MAN02 段的值(在一个可能有几十个 HL1Loops 的文件中。我认为没有必要包含超过重现问题的最低限度。如果我能得到正确的 XPath,我可以继续我的快乐方式。
    • 我想我找到了解决方案,发布了答案。
    【解决方案3】:

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

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

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

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

    有时,您必须休息一晚,才能对问题有新的认识。 我之前尝试的问题:

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

    2) 我使用 .// 而不是 ..// (一个点是 self,两个点是 parent)。 既然找到了MAN02,就得上两个家长(一个家长带mae回MAN,另一个家长带我回HLLOOP1)。

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

    【讨论】:

    • 这(除其他外)不必要的复杂。这些条件适用于“正在前往”MAN02 的HLLoop1。这就是应该表达的地方,而不是在树中向上返回。
    • 同意,已更新。我无法让 s0:HLLoop1 在 BizTalk 中工作,但这将是另一个问题。
    猜你喜欢
    • 2018-11-10
    • 2015-08-26
    • 2013-06-03
    • 2019-08-26
    • 2010-10-16
    • 2010-11-24
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多