我有两个相互关联的连续元素列表。我想把它们结合起来,但我的解决方案既慢又不优雅。我正在使用XSLT 2.0,Saxon。
List1.xml:
<data>
<w tag="a">asda</w>
<w tag="c">sdsd</w>
<w tag="a">value2</w>
<w tag="f">fdxcc</w>
<w tag="c">no</w>
</data>
List2.xml:
<data>
<w class="2">asda</w>
<w class="5">sdsd</w>
<w class="6">value2</w>
<w class="1">fdxcc</w>
<w class="2">no</w>
</data>
请注意,@ class,@ tag或元素内容的值都是唯一的;链接它们的是相同的内容和相同的序列。 (请注意,实际问题更复杂,因为我需要使用第二个列表的元素来评估第一个列表的元素。)
预期结果(相同顺序:)
<w tag="a" class="2">asda</w>
<w tag="c" class="5">sdsd</w>
<w tag="a" class="6">value2</w>
<w tag="f" class="1">fdxcc</w>
<w tag="c" class="2">no</w>
现在显而易见的方法就是通过一个列表然后选择 来自第二个的值。我是这样做的:
<xsl:template match="/">
<xsl:variable name="list1" select="doc('list1.xml')">
<xsl:variable name="list2" select="doc(*list2.xml')">
<xsl:for-each select="$list1//w">
<xsl:copy>
<xsl:copy-of select="@tag"/>
<xsl:variable name="thispos" select="position()"/>
<xsl:copy-of select="$list2//w[position()=$thispos]/@id"/>
<xsl:copy-of select="@text()"/>
</xsl:copy>
</xsl:for-each>
我有两个问题: (a)是否真的没有更好的方法来引用$ list1中的位置而不是将其保存在变量中? (b)与这个问题有关:在处理数十万件物品时,这个解决方案太慢了。什么是更好的解决方案?
答案 0 :(得分:1)
如果我理解正确,您可以匹配公共值或位置。这里匹配价值:
XSLT 2.0
<xsl:stylesheet version="2.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="w" use="." />
<xsl:template match="/">
<root>
<xsl:for-each select="data/w">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:copy-of select="key('list2', ., document('List2.xml'))/@*"/>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
此处匹配&#34;位置&#34;:
XSLT 2.0
<xsl:stylesheet version="2.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="w" use="count(preceding-sibling::w)" />
<xsl:template match="/">
<root>
<xsl:for-each select="data/w">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:copy-of select="key('list2', count(preceding-sibling::w), document('List2.xml'))/@*"/>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
在这两种情况下,结果是:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<w tag="a" class="2">asda</w>
<w tag="c" class="5">sdsd</w>
<w tag="a" class="6">value2</w>
<w tag="f" class="1">fdxcc</w>
<w tag="c" class="2">no</w>
</root>
注意强>:
正如我之前提到的,如果这不是你的最终结果,那么就没有必要构建它。正如你所看到的,&#34;其他&#34;值总是可以从List1的上下文中获得 - 您只需要在需要时指向它..
答案 1 :(得分:0)
这个问题已经解决了,但是为了防止任何人试图连接两个节点列表,我使用了这里的解决方案:Using xslt get node value at X position
<xsl:for-each select="items[not(@save)]/text">
<xsl:variable name="pos" select="position()" />
<option>
<xsl:attribute name="value"><xsl:value-of select="../../items[@save]/text[position() = $pos]" /></xsl:attribute>
<xsl:value-of select="."/>
</option>
</xsl:for-each>
这允许我组合两组节点来创建带有值的HTML选项列表,使用XSLT 1.0。