2 Stimmen

XSL-zu-XML-Schleifenproblem

Ich muss ein XML-Dokument in eine Schleife legen. Das ist kein Problem.
Das Problem tritt auf, wenn ich Text aus der vorherigen Zeile benötige, die ich gerade übersprungen habe.

Die XML-Datei wird etwa so aussehen

<lines>
  <line>
    <id>1</id>
    <text>Some fancy text here 1</text>
  </line>
  <line>
    <id></id>
    <text>This I need in the next line with a ID</text>
  </line>
  <line>
    <id></id>
    <text>Also need this.</text>
  </line>
  <line>
    <id>4</id>
    <text>Here we go</text>
  </line>
</lines>

Die XML-Ausgabedatei muss wie folgt aussehen

<output>
  <line>
    <id>1</id>
    <note>Some fancy text here 1</note>
  </line>
  <line>
    <id>4</id>
    <note>Here we go</note>
    <extra>
      <note>This I need in the next line with a ID</note>
      <note>Also need this.</note>
    </extra>
  </line>
</output>

Das XSL, das ich so weit habe, ist einfach, um die Zeilen auszusortieren, die keine ID gesetzt haben.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <output>
    <xsl:for-each select="lines/line">
      <xsl:if test="id/text() &gt; 0">
        <line>
          <id>
            <xsl:value-of select="id" />
          </id>
          <note>
            <xsl:value-of select="text" />
          </note>
        </line>
      </xsl:if>
    </xsl:for-each>
    </output>
  </xsl:template>
</xsl:stylesheet>

2voto

amelvin Punkte 8819

Sie müssen die Vorgänger-Geschwister auswählen; es gibt eine Beispiel hier .

Grundsätzlich würde die xpath-Syntax für Sie in etwa so aussehen (nicht getestet):

preceding-sibling::NodeName[1]

1voto

Emiliano Poggi Punkte 23692

Ich habe nicht widerstehen können, Ihren Code vollständig zu überprüfen :)

Hier folgt eine komplette XSLT 1.0 Lösung, die eher funktional orientiert ist (kein prozeduraler Ansatz). Es mag auf den ersten Blick unübersichtlich erscheinen, aber imho ist es ein sehr gutes Beispiel für den Einstieg in den XSLT-Templating-Mechanismus.

Auch mit xsl:for-each ist in Ihrem speziellen Fall nicht so einfach, denn in einem bestimmten Schritt der Schleife wollen Sie alle vorhergehenden benachbarten Geschwister mit leeren id , ohne zu wissen, wie viele es sind a priori .

Ich habe auch die Identitätsvorlage um die Wiederherstellung des Ziels zu vereinfachen.

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

    <!-- identity template -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <!-- match line with empty id and do not output -->
    <xsl:template match="line[not(boolean(id/text()))]"/>

    <!-- match line with id and build output -->
    <xsl:template match="line[boolean(id/text())]">
        <xsl:copy>
            <xsl:copy-of select="id"/>
            <xsl:apply-templates select="text"/>
            <extra>
                <!-- apply recursive template to the first preceding 
                sibling adajacent node with empty id -->
                <xsl:apply-templates select="(preceding-sibling::*[1])
                    [name()='line' and not(boolean(id/text()))]/text" 
                    mode="extra"/>
            </extra>
        </xsl:copy>
    </xsl:template>

    <!-- change text element to note --> 
    <xsl:template match="text">
        <note>
            <xsl:value-of select="."/>
        </note>
    </xsl:template>

    <!-- recursive template for extra note elements -->
    <xsl:template match="text" mode="extra">
        <note>
            <xsl:value-of select="."/>
        </note>
        <xsl:apply-templates select="(parent::line/preceding-sibling::*[1])
            [name()='line' and not(boolean(id/text()))]/text" 
            mode="extra"/>
    </xsl:template>

</xsl:stylesheet>

Angewandt auf Ihren Beitrag, gibt:

<?xml version="1.0" encoding="UTF-8"?>
<lines>
   <line>
      <id>1</id>
      <note>Some fancy text here 1</note>
      <extra/>
   </line>
   <line>
      <id>4</id>
      <note>Here we go</note>
      <extra>
         <note>Also need this.</note>
         <note>This I need in the next line with a ID</note>
      </extra>
   </line>
</lines>

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X