XSLT 比较列表和输出单个节点

XSLT compare lists and output single node

我正在尝试比较 2 个列表,如果有 1 个或多个节点没有出现在另一个列表中,我想在结果 xml.

中输出一个节点

示例XML:

<Root>
  <Layers>
    <List1>
      <Name>test1</Name>
      <Name>test2</Name>
      <Name>test3</Name>
    </List1>
  </Layers>
  <MoreLayers>
    <List2>
      <Name>test1</Name>
      <Name>test4</Name>
      <Name>test5</Name>
    </List2>
  </MoreLayers>
</Root>

应该看到 test2 和 test3 没有出现在 List2 中并给出以下输出:

<RootOut>
  <UniqueNames>Yes</UniqueNames>
</RootOut>

我试过在 List1 上使用 for-each 循环并与 List2 进行键比较,但这最终会为每个唯一名称创建 1 个节点,因此会在输出中输出 2 <UniqueNames>Yes</UniqueNames> 个节点。我确定我缺少一些简单的东西,但我无法弄清楚。

XSLT:

  <xsl:variable name="list1_names" select="/Root/Layers/List1/Name"/>

  <xsl:key name="list2_lookup" match="/Root/MoreLayers/List2" use="Name"/>

  <xsl:template match="/*">
    <RootOut>
      <xsl:call-template name="UniqueNames" />
    </policy>
  </xsl:template>

  <xsl:template name="UniqueNames">
        <xsl:for-each select="$list1_names">
          <xsl:if test="(not(key( 'list2_lookup', Name )))">
            <UniqueNames>Yes</UniqueNames>
          </xsl:if>
        </xsl:for-each>
  </xsl:template>

简单的怎么样:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="list2" match="List2/Name" use="." />

<xsl:template match="/Root">
    <RootOut>
        <xsl:if test="Layers/List1/Name[not(key('list2', .))]">
            <UniqueNames>Yes</UniqueNames>
        </xsl:if>
    </RootOut>
</xsl:template>

</xsl:stylesheet>

请注意,这仅测试 List1 中是否存在未出现在 List2 中的 Name,而不是相反(您的描述在这一点上有些模糊).


另一种选择是从相反的方向看:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="list1" match="List1/Name" use="." />

<xsl:template match="/Root">
    <RootOut>
        <xsl:if test="count(Layers/List1/Name) > count(key('list1', MoreLayers/List2/Name))">
            <UniqueNames>Yes</UniqueNames>
        </xsl:if>
    </RootOut>
</xsl:template>

</xsl:stylesheet>