我有这个 xsl 1.0 调用模板。 它采用两个 xml 元素,作为参数给出,并返回一个从两个参数创建的元素,但具有不同的元素。所有双打都应该被删除
<xsl:template name="distinctElements">
<xsl:param name="xml1"/>
<xsl:param name="xml2"/>
<xsl:variable name="combined-nodes">
<xsl:copy-of select="$xml1"/>
<xsl:copy-of select="$xml2"/>
</xsl:variable>
<xsl:variable name="distinct-elements">
<xsl:for-each select="$combined-nodes/*[not(. = preceding-sibling::*)]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:variable>
<xsl:for-each select="$distinct-elements/*">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
我的问题是,它不起作用。 具体来说,这段代码会产生问题:
<xsl:variable name="distinct-elements">
<xsl:for-each select="$combined-nodes/*[not(. = preceding-sibling::*)]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:variable>
似乎根本无法遍历“$combined-nodes”。 如果我使用 $xml1 或 $xml2 而不是 $combined-nodes,则此代码片段有效。
我不明白。 有人在这里看到我的问题是什么吗?
谢谢你的帮助。
我用 $xml1 和 $xml2 交换了 $combined-nodes 并且代码有效。仅当使用组合元素时,代码不起作用。
编辑: 我研究了 muenchian 方法,并将对其进行更深入的研究。目前我真的不知道如何使它适应我的特殊情况。因为我要处理的 XML 非常通用:
<someuserdata>
<item>
<name>foo</name>
<value>bar</value>
</item>
<item>
<name>foo</name>
<value>bar</value>
</item>
...
</someuserdata>
<someappointmentdata>
<item>
<name>foo</name>
<value>bar</value>
</item>
<item>
<name>foo</name>
<value>bar</value>
</item>
...
</someappointmentdata>
它包含来自不同数据库的具有不同信息的数据,所有这些数据都组合在一个 xml 文件中,嵌套在不同的级别。
xsl 以通用方式处理此 xml,只是通过检查某些“名称”-值而有所不同。
我尝试了 John Ernst 提供的代码示例,但无法正常工作。 我决定放弃调用模板的使用,并尝试减少代码以仅在我的代码的调用部分工作:
<xsl:template name="table_parent">
<xsl:param name="basis1" />
<xsl:param name="basis2" />
<xsl:variable name="basis3">
<xsl:copy-of select="xmlns:node-set($basis1 | $basis2)/*[not(. = preceding-sibling::*)]"/>
</xsl:variable>
<xsl:for-each select="$basis3/*">
如您所见,我只是想遍历我的两个 xml 元素(basis1 和 basis2)的不同总和。
但即使是这条简单的线也行不通。我的前缀是 xmlns,我已经在这个例子中改变了它。
这不应该工作吗?
感谢您的耐心和帮助
编辑: 我这里有一些示例代码: XML:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="TEST.xsl"?>
<Root>
<source1>
<Zusatzinformation>
<item>
<Name>Bemerkung</Name>
<Wert>yyy</Wert>
<Attribut>NEU</Attribut>
</item>
<item>
<Name>Versicherungsart</Name>
<Wert>-kein Eintrag-</Wert>
<Attribut>Unverändert</Attribut>
</item>
<item>
<Name>Zusatzversichert</Name>
<Wert>nein</Wert>
<Attribut>Unverändert</Attribut>
</item>
<Anordner>
<CTSmartMitarbeiter>
<CTSmartId>
<item>
<Name>ID</Name>
<Wert>-1</Wert>
<Attribut>Unverändert</Attribut>
</item>
</CTSmartId>
</CTSmartMitarbeiter>
</Anordner>
</Zusatzinformation>
</source1>
<source2>
<Zusatzinformation>
<item>
<Name>Versicherungsart</Name>
<Wert>-kein Eintrag-</Wert>
<Attribut>Unverändert</Attribut>
</item>
<item>
<Name>Zusatzversichert</Name>
<Wert>nein</Wert>
<Attribut>Unverändert</Attribut>
</item>
<Anordner>
<CTSmartMitarbeiter>
<CTSmartId>
<item>
<Name>ID</Name>
<Wert>-1</Wert>
<Attribut>Unverändert</Attribut>
</item>
</CTSmartId>
</CTSmartMitarbeiter>
</Anordner>
</Zusatzinformation>
</source2>
</Root>
xsl:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl">
<xsl:template match="/">
<xsl:variable name="source1" select="//source1"/>
<xsl:variable name="source2" select="//source2"/>
<xsl:variable name="combined-nodes" select="$source1 | $source2"/>
<xsl:variable name="distinct-elements" select="exsl:node-set($combined-nodes)"/>
<xsl:variable name="basis3">
<xsl:copy-of select="exsl:node-set($distinct-elements)/*[not(. = preceding-sibling::*)]"/>
</xsl:variable>
<xsl:for-each select="basis3/*">
<xsl:value-of select="."/><xsl:text> - </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
xsl 应该只输出一个不同的列表:
Bemerkung 复习艺术 Zusatzversichert
谢谢大家。在您的帮助下,我找到了这个解决方案:
<xsl:template name="distinctElements">
<xsl:param name="xml1"/>
<xsl:param name="xml2"/>
<xsl:variable select="exsd:node-set($xml1|$xml2)" name="combined-nodes"/>
<xsl:variable name="result">
<xsl:for-each select="$combined-nodes/item[count(. | key('item-by-name', Name)[1]) = 1]">
<itemname><xsl:copy-of select="."/></itemname>
</xsl:for-each>
</xsl:variable>
<xsl:copy-of select="$result"/>
</xsl:template>
因为我需要模板的输出作为节点集,所以我在调用后转换它:
<xsl:variable name="basis3Rtf">
<xsl:call-template name="distinctElements">
<xsl:with-param name="xml1" select="$basis1"/>
<xsl:with-param name="xml2" select="$basis2"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="basis3" select="exsd:node-set($basis3Rtf)/itemname" />
<xsl:for-each select="$basis3/*">
考虑以下示例:
XML
<Root>
<source1>
<Zusatzinformation>
<item>
<Name>Bemerkung</Name>
<Wert>yyy</Wert>
<Attribut>NEU</Attribut>
</item>
<item>
<Name>Versicherungsart</Name>
<Wert>-kein Eintrag-</Wert>
<Attribut>Unverändert</Attribut>
</item>
<item>
<Name>Zusatzversichert</Name>
<Wert>nein</Wert>
<Attribut>Unverändert</Attribut>
</item>
<Anordner>
<CTSmartMitarbeiter>
<CTSmartId>
<item>
<Name>ID</Name>
<Wert>-1</Wert>
<Attribut>Unverändert</Attribut>
</item>
</CTSmartId>
</CTSmartMitarbeiter>
</Anordner>
</Zusatzinformation>
</source1>
<source2>
<Zusatzinformation>
<item>
<Name>Versicherungsart</Name>
<Wert>-kein Eintrag-</Wert>
<Attribut>Unverändert</Attribut>
</item>
<item>
<Name>Zusatzversichert</Name>
<Wert>nein</Wert>
<Attribut>Unverändert</Attribut>
</item>
<Anordner>
<CTSmartMitarbeiter>
<CTSmartId>
<item>
<Name>ID</Name>
<Wert>-1</Wert>
<Attribut>Unverändert</Attribut>
</item>
</CTSmartId>
</CTSmartMitarbeiter>
</Anordner>
</Zusatzinformation>
</source2>
</Root>
使用(第一部分)Muenchian 分组:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:key name="item-by-name" match="item" use="Name" />
<xsl:template match="/Root">
<xsl:for-each select="*/Zusatzinformation/item[count(. | key('item-by-name', Name)[1]) = 1]">
<xsl:value-of select="Name"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
结果
Bemerkung
Versicherungsart
Zusatzversichert
请注意,一些 XSLT 1.0 处理器支持
distinct()
扩展功能,这可以使这项任务变得更加容易。
这是您可能会觉得有用的简化版本。
<!-- Call your template -->
<xsl:variable name="distinct">
<xsl:call-template name="distinctElements">
<xsl:with-param name="xml1" select="$test1"/>
<xsl:with-param name="xml2" select="$test2"/>
</xsl:call-template>
</xsl:variable>
<!-- Convert the RTF to a node-set. Use your own prefix if not exsl. -->
<xsl:variable name="distinct-elements" select="exsl:node-set($distinct)"/>
<xsl:template name="distinctElements">
<xsl:param name="xml1"/>
<xsl:param name="xml2"/>
<xsl:variable name="combined-nodes">
<xsl:copy-of select="$xml1"/>
<xsl:copy-of select="$xml2"/>
</xsl:variable>
<!-- Convert RTF to node-set. -->
<xsl:copy-of select="exsl:node-set($combined-nodes)/*[not(. = preceding-sibling::*)]"/>
</xsl:template>