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

これらのノードを同時に反復処理して、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

私は次のことが仕事をしていると思います(要素の子要素の数と名前に関係なく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 に答える
0

それを行うための組み込みの方法が XSLT にあるとは思いません。MapReduce手法を適用することで、自分で簡単に実装できると思います。

于 2012-11-14T13:42:44.280 に答える