XSL - Bestimmten Teil aus XML ansprechen (For-each select ... where ...)

banshe

Mitglied
Hallo zusammen

Ich habe neuerdings kurzzeitig mit XSL zu tun und bräuchte mal eure hilfe.. :)

Ich habe ein XML das etwa wie folgt aufgebaut ist:

Code:
  <belege>

    <!-- Abteilung A-->

    <beleg>
      <belegID>999</belegID>
      <abteilung>A</abteilung>
      <debitor>
        <personID>999</personID>
        <korrSprache>d</korrSprache>
        <geschlecht>m</geschlecht>
        <name>Peter</name>
        <vorname>Muster</vorname>
      </debitor>
      <positionen>
        ...
        ...
        ...
      </positionen>
    </beleg>




    <!-- Abteilung B-->

    <beleg>
      <belegID>888</belegID>
      <abteilung>B</abteilung>
      <debitor>
        <personID>999</personID>
        <korrSprache>d</korrSprache>
        <geschlecht>m</geschlecht>
        <name>Peter</name>
        <vorname>Muster</vorname>
      </debitor>
      <positionen>
        ...
        ...
        ...
      </positionen>
    </beleg>

  </belege>

Ich möchte jetzt eine Ausgabe tätigen, und zwar möchte ich zum Beispiel die Anrede, den Namen, den Vornamen und die BelegID von dem Beleg der Abteilung B.

Also falls im XML als Geschlecht "m" eingetragen ist, soll die Ausgabe "Herr" sein..:

Herr
Muster Peter
888

Wie kann ich das am besten machen? Wie kann ich nur die Attribute der Abteilung "B" ansprechen?

Bitte um hilfe...

Danke vielmals!
banshe
 
Mit XSLT 2.0 (also etwa mit Saxon 9 oder mit AltovaXML)
XML:
<xsl:template match="/">
  <xsl:apply-templates select="//beleg[abteilung = 'B']"/>
</xsl:template>

<xsl:template match="beleg">
  <xsl:apply-templates select="debitor, belegID"/>
</xsl:template>

<xsl:template match="debitor">
  <xsl:apply-templates select="geschlecht">
  <xsl:value-of select="name, vorname" separator=" "/>
</xsl:template>

<xsl:template match="debitor/geschlecht[. = 'm']">
  <xsl:text>Herr </xsl:text>
</xsl:template>

<xsl:template match="debitor/geschlecht[. = 'w']">
  <xsl:text>Frau </xsl:text>
</xsl:template>

So als Ergebnis nicht einfach nur Text, sondern HTML oder wieder XML erstellt werden soll, muss man halt noch Resultatselemente einfügen, aber du hast uns keinerlei Details zum Ausgabeformat mitgeteilt, also belasse ich es bei einfachem Text.
 
Hallo Martin Honnen

Vielen Dank für deine Antwort.

Schlussendlich werde ich das ganze in HTML ausgeben. Die Vorgabe ist das ganze mit XSLT 1.0 zu lösen. Das ist wahrscheinlich auch der Grund für einige Fehlermeldungen die ich bekomme wenn ich deinen Code einbaue.

Beispielsweise erhalte ich bei folgender Zeile 40:
Code:
39: <xsl:template match="debitor">
40:   <xsl:value-of select="name, vorname" separator=" "/>
41: </xsl:template>

folgende Fehlermeldung:
Fehlerlevel: error
Beschreibung: Attribute separator is not allowed on this element
Anfang: 40:0

Wie kann ich das ganze in XSLT 1.0 realisieren?

Vielen Dank und Gruss
 
Mit XSLT 1.0 braucht man etwas mehr Code:
XML:
<xsl:template match="/">
  <xsl:apply-templates select="//beleg[abteilung = 'B']"/>
</xsl:template>
 
<xsl:template match="beleg">
  <p>
    <xsl:apply-templates select="debitor"/>
    <br/>
    <xsl:apply-templates select="belegID"/>
  </p>
</xsl:template>
 
<xsl:template match="debitor">
  <xsl:apply-templates select="geschlecht">
  <br/>
  <xsl:value-of select="concat(name, ' ', vorname)"/>
</xsl:template>
 
<xsl:template match="debitor/geschlecht[. = 'm']">
  <xsl:text>Herr</xsl:text>
</xsl:template>
 
<xsl:template match="debitor/geschlecht[. = 'w']">
  <xsl:text>Frau</xsl:text>
</xsl:template>
Ich habe auch etwas HTML eingebaut, nur als Beispiel, eventuell ist die Verwendung einer Tabelle oder Liste sinnvoller als die eines Paragrafen mit Zeilenumbrüchen, aber das solltest du anpassen können. Falls nicht, poste mal das HTML, das aus den Eingabedaten erzeugt werden soll.
 
Hallo und vielen Dank für deine Hilfe!

Mein XSLT Code sieht derzeit wie folgt aus:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
        <xsl:apply-templates select="//beleg[belegID = '888']"/>
    </xsl:template>

    <xsl:template match="beleg">
        <p>
            <xsl:apply-templates select="debitor"/>
            <xsl:apply-templates select="belegID"/>
        </p>
    </xsl:template>

    <xsl:template match="debitor/geschlecht[. = 'm']">
        <xsl:text>Herr</xsl:text>
    </xsl:template>

    <xsl:template match="debitor/geschlecht[. = 'w']">
        <xsl:text>Frau</xsl:text>
    </xsl:template>

    <xsl:template match="debitor">
        <xsl:apply-templates select="geschlecht"/>
        <br/>
        <xsl:value-of select="concat(name, ' ', vorname)"/>
        <br/>
        <xsl:value-of select="strasse"/>
        <br/>
        <xsl:value-of select="concat(plz, ' ', ort)"/>
        <br/>
        <xsl:text>Ortschaft, </xsl:text>
        <xsl:value-of select="datum"/>
        <br/>
        <xsl:text>Beleg</xsl:text>
        <br/>
        <xsl:text>Kunden Nr.</xsl:text>
        <br/>
        <xsl:value-of select="personID"/>
        <br/>
        <xsl:text>Beleg Nr.</xsl:text>
        <br/>
    </xsl:template>
</xsl:stylesheet>

Als Ausgabe erhalte ich folgendes:
Herr
Muster Peter
Strassenname
PLZ Ort
Ortschaft, 2012-01-01T10:00:00
Rechnung
Kunden Nr.
33
888

Mit der Ausgabe bin ich zufrieden. Nur weiss ich nicht weiter...
Die "BelegID" hole ich aus der Ebene über "Debitor".. also aus der Ebene "Rechnung". Und zwar mit dem Teil:
Code:
    <xsl:template match="rechnung">
        <p>
            <xsl:apply-templates select="debitor"/>
            <xsl:apply-templates select="belegID"/>
        </p>
    </xsl:template>

Wie kann ich nach der BelegID weitere Attribute aus der Ebene "Debitor" holen?

Ich habe auch folgendes Versucht:
Code:
    <xsl:template match="beleg">
        <p>
            <xsl:apply-templates select="debitor"/>
            <xsl:apply-templates select="beleg"/>
        </p>
    </xsl:template>

...
...
...

    <xsl:template match="beleg">
        <xsl:apply-templates select="belegID"/>
        <br/>
        <xsl:text>Beleg Nr.</xsl:text>
        <br/>
        <xsl:value-of select="belegID"/>
    </xsl:template>

Aber das gibt mir dann nurnoch folgendes aus:
888
Beleg Nr.
888

Der ganze Rest ist weg... ich verstehe die Logik dahinter nicht wirklich... was verstehe ich falsch?

Ah und btw.:
Das Attribut "datum" hat folgenden Wert, welcher auch ausgegeben wird: "2012-01-01T10:00:00"
Ist es möglich bei der Ausgabe nur die ersten 10 Ziffern anzuzeigen und die letzten 9 Ziffern zu löschen?

Ist es möglich das Aktuelle Datum anzuzeigen? Eine Art TimeStamp?


Vielen vielen Dank und Gruss...
banshe
 
Hi.
Die "BelegID" hole ich aus der Ebene über "Debitor".. also aus der Ebene "Rechnung". Und zwar mit dem Teil:
Code:
    <xsl:template match="rechnung">
        <p>
            <xsl:apply-templates select="debitor"/>
            <xsl:apply-templates select="belegID"/>
        </p>
    </xsl:template>

Wie kann ich nach der BelegID weitere Attribute aus der Ebene "Debitor" holen?

Ich habe auch folgendes Versucht:
Code:
    <xsl:template match="beleg">
        <p>
            <xsl:apply-templates select="debitor"/>
            <xsl:apply-templates select="beleg"/>
        </p>
    </xsl:template>

...
...
...

    <xsl:template match="beleg">
        <xsl:apply-templates select="belegID"/>
        <br/>
        <xsl:text>Beleg Nr.</xsl:text>
        <br/>
        <xsl:value-of select="belegID"/>
    </xsl:template>
Du hast hier zwei Templates mit dem gleichen Muster geschrieben. Oder wie soll ich den Code verstehen?

Nur das Template mit der besten Übereinstimmung wird auch angewandt.
Der ganze Rest ist weg... ich verstehe die Logik dahinter nicht wirklich... was verstehe ich falsch?
Etwas anderes macht dein Template doch nicht... Ich verstehe nicht was du stattdessen erwartet hast.
Ah und btw.:
Das Attribut "datum" hat folgenden Wert, welcher auch ausgegeben wird: "2012-01-01T10:00:00"
Ist es möglich bei der Ausgabe nur die ersten 10 Ziffern anzuzeigen und die letzten 9 Ziffern zu löschen?
Ja, mit der XPath Function substring.
Ist es möglich das Aktuelle Datum anzuzeigen? Eine Art TimeStamp?
Nein, nur mit Erweiterungsfunktionen.

Gruß
 
Hallo und Danke für die Antwort.

Du hast hier zwei Templates mit dem gleichen Muster geschrieben. Oder wie soll ich den Code verstehen?
...
...
Etwas anderes macht dein Template doch nicht... Ich verstehe nicht was du stattdessen erwartet hast.

Wie gesagt, ich bin frisch in XSLT und weiss solche sachen nicht.. Ich muss XSLT auch in keinem hohen Niveau kennen, ich brauche einzig die Grundlagen.

Bei meinem Problem(chen) komme ich leider immernoch nicht weiter.
Einfacher formuliert:

Wie kann ich aus diesem XML:
Code:
<job>
  <jobDatum>2012-01-01T12:00:00</jobDatum>

  <belege>
 
    <!-- Abteilung A-->
 
    <beleg>
      <belegID>999</belegID>
      <abteilung>A</abteilung>
      <anz>20</anz>
      <text>Test Text</text>

      <debitor>
        <personID>89</personID>
        <korrSprache>d</korrSprache>
        <geschlecht>m</geschlecht>
        <name>Peter</name>
        <vorname>Muster</vorname>
        <strasse>Langstrasse 1</strasse>
        <ort>80331 München</ort>
      </debitor>

      <positionen>
        <positionID>1</positionID>
        <betrag>100</betrag>
        <text>Belegtext</text>
      </positionen>

      <positionen>
        <positionID>2</positionID>
        <betrag>200</betrag>
        <text>Belegtext</text>
      </positionen>
    </beleg>
 
 
 
 
    <!-- Abteilung B-->
 
    <beleg>
      <belegID>888</belegID>
      <abteilung>A</abteilung>
      <anz>20</anz>
      <text>Test Text</text>

      <debitor>
        <personID>86</personID>
        <korrSprache>d</korrSprache>
        <geschlecht>m</geschlecht>
        <name>Fanz</name>
        <vorname>Rohr</vorname>
        <strasse>Kurzstrasse 1</strasse>
        <ort>80331 München</ort>
      </debitor>

      <positionen>
        <positionID>3</positionID>
        <betrag>300</betrag>
        <text>Belegtext</text>
      </positionen>

      <positionen>
        <positionID>4</positionID>
        <betrag>5500</betrag>
        <text>Belegtext</text>
      </positionen>
    </beleg>
  </belege>
</job>

Folgende Ausgabe (Alles aus der "Abteilung B"):
Code:
Herr     //Kommt aus dem "m" heraus
Franz Rohr
Kurzstrasse 1
80331 München
München, 2012-01-01     //Kommt aus <ort> und <jobDatum> heraus
86     //<personID>
888     //<belegID>
Belegtext 3
300     //<betrag>
Belegtext 4
5500     //<betrag>
20     //<anz>


Irgendwie fehlt mir das Verständniss für XSLT...
Vielen vielen Dank für die Hilfe!!

Gruss
 
Hi.

Du solltest dich evtl. erstmal mit XPath befassen. Dein Problem ist ziemlich simpel, mehr als Grundlagen braucht man dafür nicht.

XML:
<xsl:template match="beleg[abteilung = 'B']">
  <xsl:value-of select="debitor/vorname" /> <xsl:value-of select="debitor/name" />
  <xsl:value-of select="debitor/strasse" />
  ...

  <xsl:for-each select="positionen">
    <xsl:value-of select="text" /> <xsl:value-of select="positionID" />
    <xsl:value-of select="betrag" />
  </xsl:for-each>
<xsl:template>
Gruß
 
Zuletzt bearbeitet von einem Moderator:
Hallo deepthroat

Danke für deine Antwort. Ich habe dies soeben ausprobiert.
Wenn ich genau deinen Code verwende:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="beleg[abteilung = 'B']">
        <xsl:value-of select="debitor/vorname"/>
        <xsl:value-of select="debitor/name"/>
        <xsl:value-of select="debitor/strasse"/>

        <xsl:for-each select="positionen">
            <xsl:value-of select="text"/>
            <xsl:value-of select="positionID"/>
            <xsl:value-of select="betrag"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

bekomme ich das ganze XML als Resultat:
Code:
2012-01-01T12:00:00 999 A 20 Test Text 89 d m Peter Muster Langstrasse 1 80331 München 1 100 Belegtext 2 200 Belegtext 888 A 20 Test Text 86 d m Fanz Rohr Kurzstrasse 1 80331 München 3 300 Belegtext 4 5500 Belegtext

Habe ich etwas falsch gemacht?

Danke und Gruss
 
Zurück