1

我有一个这样的 XML:

<xml>
    <node1>1.1</node1>
    <node1>1.2</node1>
    <node1>1.3</node1>

    <node2>2.1</node2>
    <node2>2.2</node2>
    <node2>2.3</node2>

    <node3>3.1</node3>
    <node3>3.2</node3>
    <node3>3.3</node3>
</xml>

我想得到以下输出:
line: 1.1 + 2.1 + 3.1
line: 1.2 + 2.2 + 3.2
line: 1.3 + 2.3 + 3.3

有没有一种方法可以同时遍历这些节点并跟踪我在三个列表中的每一个中的当前位置,或者我是否必须将这些项目包装到一个更大的块中并遍历块?

我正在使用 XSL 1.0。

4

3 回答 3

2

就这么简单

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node1">
   <xsl:variable name="vPos" select="position()"/>
     <xsl:value-of select=". + ../node2[$vPos] + ../node3[$vPos]"/>
     <xsl:text>&#xA;</xsl:text>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时(基于提供的文档):

<xml>
    <node1>1</node1>
    <node1>2</node1>
    <node1>3</node1>

    <node2>4</node2>
    <node2>5</node2>
    <node2>6</node2>

    <node3>7</node3>
    <node3>8</node3>
    <node3>9</node3>
</xml>

产生了想要的正确结果

12
15
18

请注意

  1. 在 XSLT 1.0 和 XSLT 2.0 中,可以使用FXSL模板/函数zip-with3()

  2. 在 XPath 3.0 (XSLT 3.0) 中会有一个标准函数map-pairs(),但是没有map-tripples()标准函数。可以使用此函数生成中间结果,然后再次使用它来生成最终结果。

  3. 正如 Ian Roberts 所指出的xsl:strip-space,此解决方案中的存在很重要 - 没有它,position()函数会产生不同的结果,并且转换不会按要求执行。

于 2012-11-14T13:57:05.317 回答
0

我认为 XSLT 中没有内置的方法可以做到这一点。我想您可以通过应用MapReduce技术轻松地自己实现它。

于 2012-11-14T13:42:44.280 回答
0

我认为以下内容可以完成工作(与元素的子元素的数量和名称无关xml):

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text"/>

<xsl:key name="name" match="xml/*" use="local-name()"/>

<xsl:variable name="first" select="xml/*[generate-id() = generate-id(key('name', local-name())[1])]"/>

<xsl:template match="xml">
  <xsl:apply-templates select="$first[1]" mode="init"/>
</xsl:template>

<xsl:template match="xml/*" mode="init">
  <xsl:apply-templates select="key('name', local-name())" mode="line"/>
</xsl:template>

<xsl:template match="xml/*" mode="line">
  <xsl:variable name="pos" select="position()"/>
  <xsl:text>line: </xsl:text>
  <xsl:for-each select="$first">
    <xsl:if test="position() > 1"><xsl:text> + </xsl:text></xsl:if>
    <xsl:apply-templates select="key('name', local-name())[$pos]"/>
  </xsl:for-each>
  <xsl:text>&#10;</xsl:text>
</xsl:template>

<xsl:template match="xml/*">
  <xsl:value-of select="."/>
</xsl:template>

</xsl:stylesheet>
于 2012-11-14T14:09:59.270 回答