Frage

Ich bin eine große Wortdatei mit Test-Beschreibungen Parsen und habe ein Problem des Umfangs der Knoten. Word erstellt im Grunde eine Liste von Absätzen und ich möchte gruppieren sie in einen übergeordneten Knoten. Also für jeden Knoten ‚A‘ Ich möchte Gruppe alle folgenden Knoten bis zu dem nächsten Knoten ‚A‘ in ‚A‘.

Wie kann dies mit XSL getan werden?

Beispiel: Ich habe bekommen zu:

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

Aber Notwendigkeit:

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

Danke!     

War es hilfreich?

Lösung

Wenn Sie meinen, alle Knoten folgende <A> übereinstimmen, aber kommen, bevor die nächste <A>, ich glaube, Sie so etwas wie diese verwenden können:

<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>

Für Ihre Eingabe:

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

Ich bekomme (ich verließ den „Bereich“ -Attribut in die Berechnungen sichtbar zu machen):

<A range="2-3">
  <ab />
  <ac />
</A>
<A range="5-6">
  <ab />
  <ac />
</A>

Andere Tipps

Es ist eine einfache und sehr leistungsfähige Lösung mit den Tasten.

Diese Transformation:

<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>

, wenn auf dem ursprünglichen XML-Dokument angewandt:

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

erzeugt das gewünschte Ergebnis:

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

Hinweis: , wie die Definition des <xsl:key> , mit der Verwendung des key() Funktion macht die meisten einfach und natürlich das Sammeln aller Geschwisterelemente zwischen zwei benachbarten <A/> Elemente.

XSLT 2.0-Lösung:

<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>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top