3

テストの説明を含む巨大な単語ファイルを解析していますが、ノードのスコープに問題があります。Wordは基本的に段落のリストを作成し、それらを親ノードにグループ化したいです。したがって、ノード「A」ごとに、次のノード「A」までの後続のすべてのノードを「A」にグループ化します。

これはXSLでどのように行うことができますか?

例:私は次のようになりました:

<A/>
<ab/>
<ac/>
<A/>
<ab/>
<ac/>

しかし、必要があります:

<A>
<ab/>
<ac/>
</A>
<A>
<ab/>
<ac/>
</A>

ありがとうございました!

4

3 に答える 3

4

キーを使用したシンプルで非常に強力なソリューションがあります。

この変換:

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

 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kFollowing" match="*[not(self::A)]"
  use="generate-id(preceding-sibling::A[1])"/>

    <xsl:template match="/*">
     <t>
       <xsl:apply-templates select="A"/>
     </t>
    </xsl:template>

    <xsl:template match="A">
     <A>
       <xsl:copy-of select=
          "key('kFollowing',generate-id())"/>
     </A>
    </xsl:template>
</xsl:stylesheet>

元のXMLドキュメントに適用した場合:

<t>
    <A/>
    <ab/>
    <ac/>
    <A/>
    <ab/>
    <ac/>
</t>

必要な結果を生成します。

<t>
   <A>
      <ab/>
      <ac/>
   </A>
   <A>
      <ab/>
      <ac/>
   </A>
</t>

<xsl:key>関数の使用と組み合わせたの定義が、key()2つの隣接する要素間のすべての兄弟要素を最も簡単かつ自然に収集する方法に注意してください<A/>

于 2009-03-20T03:37:52.090 に答える
3

に続くすべてのノードを一致させたい<A>が、 next の前に来る場合は、次<A>のようなものを使用できると思います。

<xsl:template match="A">
  <xsl:copy>
    <!-- start of range -->
    <xsl:variable name="start" select="count(preceding-sibling::*) + 1" />
    <!-- end of range -->
    <xsl:variable name="stop">
      <xsl:choose>
        <!-- either just before the next A node -->
        <xsl:when test="following-sibling::A">
          <xsl:value-of select="count(following-sibling::A[1]/preceding-sibling::*) + 1" />
        </xsl:when>
        <!-- or all the rest -->
        <xsl:otherwise>
          <xsl:value-of select="count(../*) + 1" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <!-- this for debugging only -->
    <xsl:attribute name="range">
      <xsl:value-of select="concat($start + 1, '-', $stop - 1)" />
    </xsl:attribute>

    <!-- copy all nodes in the calculated range -->
    <xsl:for-each select="../*[position() &gt; $start and position() &lt; $stop]">
      <xsl:copy-of select="." />
    </xsl:for-each>
  </xsl:copy>
</xsl:template>

あなたの入力のために:

<root>
  <A />
  <ab />
  <ac />
  <A />
  <ab />
  <ac />
</root>

私は取得します(計算を表示するために「範囲」属性を残しました):

<A range="2-3">
  <ab />
  <ac />
</A>
<A range="5-6">
  <ab />
  <ac />
</A>
于 2009-03-19T21:24:10.320 に答える
3

XSLT 2.0 ソリューション:

<xsl:for-each-group select="*" group-starting-with="A">
  <xsl:element name="{name(current-group()[1])}">
    <xsl:copy-of select="current-group()[position() gt 1]"/>  
  </xsl:element>
</xsl:for-each-group>
于 2009-03-20T07:03:06.093 に答える