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

时间:2011-04-03 22:07:47

标签: xml xslt match

如何匹配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>

同样的预期结果。谢谢!

1 个答案:

答案 0 :(得分:2)

此转化

<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('&#xA;  ',.,' ')"/>

  <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('&#xA;  ',.,' ')"/>

  <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('&#xA;  ',.,' ')"/>
        <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

Update3 :现在是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('&#xA;  ',.,' ')"/>
        <xsl:if test="not(. = $vDoc1/*)">
            <xsl:text>no </xsl:text>
        </xsl:if>
        <xsl:text>match</xsl:text>
    </xsl:template>
</xsl:stylesheet>