【问题标题】:XSLT: XPath comparison between two filesXSLT:两个文件之间的 XPath 比较
【发布时间】:2011-07-12 17:01:42
【问题描述】:

我想通过 XSLT 比较两个 XML 文件。如果文档 1 中特定类型的所有元素都位于文档 2 中的相同 XPath 位置,则应认为比较成功。

考虑

<entry>
    <entry1>
        <entry2>
            <value type="1"/>
        </entry2>
    </entry1>
</entry>

作为文档 1。

被观察的元素是位于entry/entry1/entry2的“value”(属性type=1)。因此,在这个意义上与

进行比较
<entry>
    <entry0/>
    <entry0/>
    <entry1>
        <entry2>
            <value type="1"/>
        </entry2>
    </entry1>
</entry>

应该被认为是成功的,而

<entry>
    <entry1>
        <value type="1"/>
    </entry1>
</entry>

不成功,因为“值”(属性 type=1)位于 entry/entry1。还 与

的比较
<entry>
    <entry1>
        <entry2>
            <value type="2"/>
        </entry2>
    </entry1>
</entry>

应该认为不成功,因为value的属性是type=2。

我在 XSLT 中完成这项任务的天真尝试是这样的:

<xsl:template match="value">
   <xsl:if test="not(document($doc2)/.[@type=@type])">
      <xsl:text>something is missing</xsl:text>
   </xsl:if>
</xsl:template>

这种方法不成功,因为在第二个文档中选择所需的 XPath 似乎不起作用。

也许您对如何解决这个问题有想法?

马特

【问题讨论】:

  • 如果您只需要测试几个元素,最好的方法可能是手动编写测试 XPath,针对不同的文件执行它们并比较结果。否则我不知道这个问题的简单解决方案。
  • 我不明白你的比较。 &lt;entry&gt;&lt;entry1&gt;&lt;entry2&gt;&lt;value type="1"/&gt;&lt;/entry2&gt;&lt;/entry1&gt;&lt;/entry&gt; entry&gt;&lt;entry0/&gt;&lt;entry0/&gt;&lt;entry1&gt;&lt;entry2&gt;&lt;value type="1"/&gt;&lt;/entry2&gt;&lt;/entry1&gt; 非常不同。为什么他们之间的比较会成功?
  • 好的,不要称它为“比较”,而是“检查 doc1 中观察到的每个元素是否存在于 doc2 中的相同 XPath 中”。我将按照以下答案中的建议尝试 deep-equal。

标签: xslt file-comparison


【解决方案1】:

您的问题被完全低估了。例如,除了要求 doc1 中的每个元素在 doc2 中都有对应的元素之外,是否还要求 doc2 中的每个元素在 doc1 中都有对应的元素?

然而,接近的情况可能是条件 “对于D1 中的每个元素V1,例如name(V1)=N,在D2 中存在一个元素V2,例如name(V2)=N and deep-equal(V1, V2) and path(V1) = path(V2),其中路径($V) 被定义为string-join($V/ancestor-or-self::*/name())",它翻译成下面的XPath 2.0 表达式:

every $V1 in $D1//N satisfies
some $V2 in $D2//N satisfies
deep-equal($V1, $V2) and
string-join($V1/ancestor-or-self::*/name())
 = string-join($V2/ancestor-or-self::*/name())  

【讨论】:

  • 很抱歉,如果您认为我的问题没有明确说明,我只是试图专注于主要方面。尤其是您的示例不相关:doc2 可能包含大量其他不会影响我感觉的比较的元素(因此“比较”一词可能具有误导性-对此感到抱歉!)无论如何,谢谢您的想法确实很有帮助。
【解决方案2】:

只是为了好玩,Kay 博士的answer 的 XSLT 1.0 翻译:

    <xsl:variable name="vTest1">
        <xsl:for-each select="$D1//value[@type]">
            <xsl:variable name="vPath1">
                <xsl:for-each select="ancestor-or-self::*">
                    <xsl:value-of select="concat('/',name())"/>
                </xsl:for-each>
            </xsl:variable>
            <xsl:variable name="vTest2">
                <xsl:for-each select="$D2//value[@type=current()/@type]">
                    <xsl:variable name="vPath2">
                        <xsl:for-each select="ancestor-or-self::*">
                            <xsl:value-of select="concat('/',name())"/>
                        </xsl:for-each>
                    </xsl:variable>
                    <xsl:if test="$vPath1=$vPath2">True</xsl:if>
                </xsl:for-each>
            </xsl:variable>
            <xsl:if test="$vTest2=''">False</xsl:if>
        </xsl:for-each>
    </xsl:variable>

那么$vTest1 = '' 将是测试的布尔值。

【讨论】:

  • 非常感谢,解决方案几乎1:1适用于我的问题。
猜你喜欢
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-19
  • 1970-01-01
相关资源
最近更新 更多