【问题标题】:xpath/xslt equal check for multiple valuesxpath/xslt 对多个值进行相等检查
【发布时间】:2013-03-06 13:48:08
【问题描述】:

例如我有一个xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<TemporaryRoot>
    <ProcessPurchaseOrder>
        <DocumentReference>
            <AlternateDocumentID>
                <ID>0171688401</ID>
            </AlternateDocumentID>
            <AlternateDocumentID>
                <ID>0171688404</ID>
            </AlternateDocumentID>
            <AlternateDocumentID>
                <ID>0171688405</ID>
            </AlternateDocumentID>
        </DocumentReference>
    </ProcessPurchaseOrder>
    <DbResponse>
        <ResultSet>
            <Row>
                <Cell name="WEANR" type="VARCHAR2">0171688401</Cell>
            </Row>
            <Row>
                <Cell name="WEANR" type="VARCHAR2">0171688404</Cell>
            </Row>
        </ResultSet>
    </DbResponse>
</TemporaryRoot>

如何编写 xpath 或 xslt 代码来检查 DbResponse/ResultSet/Row/Cell[@name="WEANR"] 是否包含来自 AlternateDocumentID/ID 的所有值

在此示例中结果为 false,因为 DbResponse/ResultSet/Row/Cell[@name="WEANR"] 没有 0171688405

【问题讨论】:

    标签: xml xslt xpath xslt-2.0


    【解决方案1】:

    您可以使用 XPath 2.0 构造,而不是 Dimitre 使用的 not(X[not(. = Y)]),这对于那些既没有数学训练也没有直观掌握符号逻辑的人来说有点难以理解。

    every $x in X satisfies (some $y in Y satisfies $x eq $y)
    

    具体

    every $id in //ID satisfies (some $cell in //Cell satisfies $id eq $cell)
    

    您还可以通过编写将这个示例的显式量化与“=”运算符的隐式量化混合在一起

    every $id in //ID satisfies ($id = //Cell)
    

    这可能是我的选择。

    【讨论】:

      【解决方案2】:

      使用这个单一的 XPath 1.0 表达式

      not(/*/ProcessPurchaseOrder
                      /*/*/ID[not(. = /*/DbResponse/*/*/Cell[@name='WEANR'])])
      

      基于 XSLT 的验证

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <xsl:output omit-xml-declaration="yes" indent="yes"/>
       <xsl:strip-space elements="*"/>
      
       <xsl:template match="/">
           <xsl:copy-of select=
           "not(/*/ProcessPurchaseOrder
                      /*/*/ID[not(. = /*/DbResponse/*/*/Cell[@name='WEANR'])])"/>
       </xsl:template>
      </xsl:stylesheet>
      

      当对提供的 XML 文档应用此转换时:

      <TemporaryRoot>
          <ProcessPurchaseOrder>
              <DocumentReference>
                  <AlternateDocumentID>
                      <ID>0171688401</ID>
                  </AlternateDocumentID>
                  <AlternateDocumentID>
                      <ID>0171688404</ID>
                  </AlternateDocumentID>
                  <AlternateDocumentID>
                      <ID>0171688405</ID>
                  </AlternateDocumentID>
              </DocumentReference>
          </ProcessPurchaseOrder>
          <DbResponse>
              <ResultSet>
                  <Row>
                      <Cell name="WEANR" type="VARCHAR2">0171688401</Cell>
                  </Row>
                  <Row>
                      <Cell name="WEANR" type="VARCHAR2">0171688404</Cell>
                  </Row>
              </ResultSet>
          </DbResponse>
      </TemporaryRoot>
      

      计算 XPath 表达式并将结果复制到输出:

      false
      

      当我们把文档改成这样的时候:

      <TemporaryRoot>
          <ProcessPurchaseOrder>
              <DocumentReference>
                  <AlternateDocumentID>
                      <ID>0171688401</ID>
                  </AlternateDocumentID>
                  <AlternateDocumentID>
                      <ID>0171688404</ID>
                  </AlternateDocumentID>
              </DocumentReference>
          </ProcessPurchaseOrder>
          <DbResponse>
              <ResultSet>
                  <Row>
                      <Cell name="WEANR" type="VARCHAR2">0171688401</Cell>
                  </Row>
                  <Row>
                      <Cell name="WEANR" type="VARCHAR2">0171688404</Cell>
                  </Row>
              </ResultSet>
          </DbResponse>
      </TemporaryRoot>
      

      应用于此文档的转换再次产生正确的结果:

      true
      

      说明

      正确使用Double-Negation Law

      【讨论】:

      • @VextoR,在这个答案中,我放置了双重否定法的链接。所以,一个集合中的所有项目都有一个属性 X,如果没有一个项目没有这个属性 X。现在,只需将上一句中的“集合”替换为 /*/ProcessPurchaseOrder/*/*/ID,将“属性 X”替换为 @ 987654329@
      【解决方案3】:

      作为 XPath 解决方案,您可以检查 Row/Cell 中与 AlternateDocumentID/ID 节点匹配的所有节点,然后将其与节点总数进行比较:

      count(//DbResponse/ResultSet/Row[Cell/@name='WEANR' and  //AlternateDocumentID/ID/text() = Cell/text()]) = count(//AlternateDocumentID/ID)
      

      对于 XSLT 解决方案,here's a good example question 了解如何执行此操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-02-10
        • 2018-09-05
        • 2018-05-13
        • 1970-01-01
        • 2012-01-06
        • 2017-06-17
        • 1970-01-01
        相关资源
        最近更新 更多