XSL:两个 xml 文档的浅比较?

发布于 2024-10-30 13:54:11 字数 1807 浏览 1 评论 0原文

如何匹配 XSLT 中的 XML 内容?我将为您提供输入 XML 文件和预期输出以及我尝试过的内容:

input1.xml

  <?xml version="1.0" ?> 
  <list1>
   <value>1</value>
   <value>2</value>
   <value>3</value>
  </list1>

input2.xml (经过编辑以显示顺序不重要)

  <?xml version="1.0" ?> 
  <list2>
   <value>3</value>
   <value>1</value>
  </list2>

所需输出(经过编辑以显示顺序不重要):

1 match
2 no match
3 match

或其任何排列。

我尝试过的:

<xsl:variable name="list1" select="document('./resources/input1.xml')"/>
<xsl:variable name="list2" select="document('./resources/input2.xml')"/>

<xsl:for-each select="$list1/list1/value">
 <xsl:variable name="check"/>
 <xsl:variable name="list1_value" select="."/>
 <xsl:for-each select="$list2/list2/value">
  <xsl:if test="$list1_value=.">
   <xsl:variable name="check" select="1"/>
  </xsl:if>
 </xsl:for-each>
 <xsl:choose>
  <xsl:when test="$check='1'">
   <xsl:value-of select="."/> match<br />
  </xsl:when>
  <xsl:otherwise>
   <xsl:value-of select="."/> no match<br />
  </xsl:otherwise>
 </xsl:choose>
</xsl:for-each>

当然这不起作用,因为它尝试使用变量作为变量:)

此外,如何将较大的列表与应用于较小列表的 XSLT 相匹配,如下所示:

XSLT 应用于 XML:

<?xml version="1.0" ?>
<list2>
 <value>1</value>
 <value>2</value>
</list2>

并且该列表作为变量导入:

<?xml version="1.0" ?>
<list1>
 <value>1</value>
 <value>2</value>
 <value>3</value>
</list1>

相同的期望结果。谢谢你!

How do I match XML content in XSLT? I'll give you the input XML files and expected output as well as what I've tried:

input1.xml

  <?xml version="1.0" ?> 
  <list1>
   <value>1</value>
   <value>2</value>
   <value>3</value>
  </list1>

input2.xml (edited to show that order should not matter)

  <?xml version="1.0" ?> 
  <list2>
   <value>3</value>
   <value>1</value>
  </list2>

desired output (edited to show that order should not matter):

1 match
2 no match
3 match

Or any permutation thereof.

What I tried:

<xsl:variable name="list1" select="document('./resources/input1.xml')"/>
<xsl:variable name="list2" select="document('./resources/input2.xml')"/>

<xsl:for-each select="$list1/list1/value">
 <xsl:variable name="check"/>
 <xsl:variable name="list1_value" select="."/>
 <xsl:for-each select="$list2/list2/value">
  <xsl:if test="$list1_value=.">
   <xsl:variable name="check" select="1"/>
  </xsl:if>
 </xsl:for-each>
 <xsl:choose>
  <xsl:when test="$check='1'">
   <xsl:value-of select="."/> match<br />
  </xsl:when>
  <xsl:otherwise>
   <xsl:value-of select="."/> no match<br />
  </xsl:otherwise>
 </xsl:choose>
</xsl:for-each>

Of course this doesn't work because it tries to use a variable as a variable :)

Additionally, how would you match the larger list to an XSLT applied to a smaller list as such:

XSLT is applied to XML:

<?xml version="1.0" ?>
<list2>
 <value>1</value>
 <value>2</value>
</list2>

And this list is imported as a variable:

<?xml version="1.0" ?>
<list1>
 <value>1</value>
 <value>2</value>
 <value>3</value>
</list1>

Same desired result. Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

能怎样 2024-11-06 13:54:11

此转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <my:doc2>
    <list2>
        <value>1</value>
        <value>2</value>
    </list2>
 </my:doc2>

 <xsl:variable name="vDoc2"
      select="document('')/*/my:doc2/*"/>

 <xsl:template match="/*/*">
  <xsl:value-of select="concat('
  ',.,' ')"/>

  <xsl:variable name="vPos" select="position()"/>
   <xsl:if test="not(. = $vDoc2/*[position()=$vPos])">
    <xsl:text>no </xsl:text>
   </xsl:if>
   <xsl:text>match</xsl:text>
 </xsl:template>
</xsl:stylesheet>

当应用于第一个提供的 XML 文档时:

<list1>
    <value>1</value>
    <value>2</value>
    <value>3</value>
</list1>

产生所需的正确结果:

  1 match
  2 match
  3 no match

更新:相同的转换,但使用两个不同的 XML 文件:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pDoc1" select="'/temp/list1.xml'"/>
 <xsl:param name="pDoc2" select="'/temp/list2.xml'"/>

 <xsl:variable name="vDoc1"
      select="document($pDoc1)/*"/>
 <xsl:variable name="vDoc2"
      select="document($pDoc2)/*"/>

 <xsl:template match="/">
  <xsl:apply-templates select="$vDoc1/*"/>
 </xsl:template>

 <xsl:template match="/*/*">
  <xsl:value-of select="concat('
  ',.,' ')"/>

  <xsl:variable name="vPos" select="position()"/>
   <xsl:if test="not(. = $vDoc2/*[position()=$vPos])">
    <xsl:text>no </xsl:text>
   </xsl:if>
   <xsl:text>match</xsl:text>
 </xsl:template>
</xsl:stylesheet>

Update2:当要比较的较短元素列表是源 XML 文档时,OP 另外需要一个解决方案:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:my="my:my">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <my:doc2>
      <list2>
        <value>1</value>
        <value>2</value>
        <value>3</value>
      </list2>
    </my:doc2>

    <xsl:variable name="vDoc1" select="/*"/>

    <xsl:variable name="vDoc2"
      select="document('')/*/my:doc2/*"/>

    <xsl:template match="/">
     <xsl:apply-templates select="$vDoc2/*"/>
    </xsl:template>
    <xsl:template match="value">
        <xsl:value-of select="concat('
  ',.,' ')"/>
        <xsl:variable name="vPos" select="position()"/>
        <xsl:if test="not(. = $vDoc1/*[position()=$vPos])">
            <xsl:text>no </xsl:text>
        </xsl:if>
        <xsl:text>match</xsl:text>
    </xsl:template>
</xsl:stylesheet>

当此转换应用于此源时XML 文档

<list1>
    <value>1</value>
    <value>2</value>
</list1>

再次产生了想要的正确结果

  1 match
  2 match
  3 no match

更新3:现在OP进行了第三次修改:两个列表中元素的顺序不一样问题...

解决方案更简单:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:my="my:my">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <my:doc2>
      <list2>
        <value>1</value>
        <value>2</value>
        <value>3</value>
      </list2>
    </my:doc2>

    <xsl:variable name="vDoc1" select="/*"/>

    <xsl:variable name="vDoc2"
      select="document('')/*/my:doc2/*"/>

    <xsl:template match="/">
     <xsl:apply-templates select="$vDoc2/*"/>
    </xsl:template>
    <xsl:template match="value">
        <xsl:value-of select="concat('
  ',.,' ')"/>
        <xsl:if test="not(. = $vDoc1/*)">
            <xsl:text>no </xsl:text>
        </xsl:if>
        <xsl:text>match</xsl:text>
    </xsl:template>
</xsl:stylesheet>

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <my:doc2>
    <list2>
        <value>1</value>
        <value>2</value>
    </list2>
 </my:doc2>

 <xsl:variable name="vDoc2"
      select="document('')/*/my:doc2/*"/>

 <xsl:template match="/*/*">
  <xsl:value-of select="concat('
  ',.,' ')"/>

  <xsl:variable name="vPos" select="position()"/>
   <xsl:if test="not(. = $vDoc2/*[position()=$vPos])">
    <xsl:text>no </xsl:text>
   </xsl:if>
   <xsl:text>match</xsl:text>
 </xsl:template>
</xsl:stylesheet>

when applied on the first provided XML document:

<list1>
    <value>1</value>
    <value>2</value>
    <value>3</value>
</list1>

produces the wanted, correct result:

  1 match
  2 match
  3 no match

Update: The same transformation, but with two different XML files:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pDoc1" select="'/temp/list1.xml'"/>
 <xsl:param name="pDoc2" select="'/temp/list2.xml'"/>

 <xsl:variable name="vDoc1"
      select="document($pDoc1)/*"/>
 <xsl:variable name="vDoc2"
      select="document($pDoc2)/*"/>

 <xsl:template match="/">
  <xsl:apply-templates select="$vDoc1/*"/>
 </xsl:template>

 <xsl:template match="/*/*">
  <xsl:value-of select="concat('
  ',.,' ')"/>

  <xsl:variable name="vPos" select="position()"/>
   <xsl:if test="not(. = $vDoc2/*[position()=$vPos])">
    <xsl:text>no </xsl:text>
   </xsl:if>
   <xsl:text>match</xsl:text>
 </xsl:template>
</xsl:stylesheet>

Update2: The OP additionally wants a solution when the shorter lists of elements to compare is the source XML document:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:my="my:my">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <my:doc2>
      <list2>
        <value>1</value>
        <value>2</value>
        <value>3</value>
      </list2>
    </my:doc2>

    <xsl:variable name="vDoc1" select="/*"/>

    <xsl:variable name="vDoc2"
      select="document('')/*/my:doc2/*"/>

    <xsl:template match="/">
     <xsl:apply-templates select="$vDoc2/*"/>
    </xsl:template>
    <xsl:template match="value">
        <xsl:value-of select="concat('
  ',.,' ')"/>
        <xsl:variable name="vPos" select="position()"/>
        <xsl:if test="not(. = $vDoc1/*[position()=$vPos])">
            <xsl:text>no </xsl:text>
        </xsl:if>
        <xsl:text>match</xsl:text>
    </xsl:template>
</xsl:stylesheet>

when this transformation is applied on this source XML document:

<list1>
    <value>1</value>
    <value>2</value>
</list1>

again the wanted, correct result is produced:

  1 match
  2 match
  3 no match

Update3: Now a third modification by the OP: The order of elements in the two lists do not matter...

The solution is even simpler:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:my="my:my">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <my:doc2>
      <list2>
        <value>1</value>
        <value>2</value>
        <value>3</value>
      </list2>
    </my:doc2>

    <xsl:variable name="vDoc1" select="/*"/>

    <xsl:variable name="vDoc2"
      select="document('')/*/my:doc2/*"/>

    <xsl:template match="/">
     <xsl:apply-templates select="$vDoc2/*"/>
    </xsl:template>
    <xsl:template match="value">
        <xsl:value-of select="concat('
  ',.,' ')"/>
        <xsl:if test="not(. = $vDoc1/*)">
            <xsl:text>no </xsl:text>
        </xsl:if>
        <xsl:text>match</xsl:text>
    </xsl:template>
</xsl:stylesheet>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文