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>
我正在尝试比较 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>