Announcement

Collapse
No announcement yet.

Reihenfolge von Tags unbekannt -> tabellarische HTML-Ausgabe?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Reihenfolge von Tags unbekannt -> tabellarische HTML-Ausgabe?

    Guten Abend,


    ich versuche momentan, aus einem SOAP-Response eine tabellarische HTML-Ausgabe der Informationen für ein Portlet zu erzeugen, was zunächst auch problemlos funktioniert hat. Heute erfuhr ich zu meiner Überraschung allerdings vom Auftraggeber, dass einige Child-Elemente in beliebiger Reihenfolge im XML auftauchen können, was meine Lösung leider ad absurdum führt.

    So sieht die entscheidende XML-Struktur aus, welche mir der Web Service schickt:

    HTML Code:
    <ROOT>
      <A>
        <id>wert</id>
        <typ>EIN_BESTIMMTER_TYP</typ>
        <date>wert</date>
        <p>
          <name>1._WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
        <p>
          <name>2._WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
        <p>
          <name>3._WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
      </A>
      <A>
        <id>wert</id>
        <typ>EIN_BESTIMMTER_TYP</typ>
        <date>wert</date>
        <p>
          <name>1._WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
        <p>
          <name>2._WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
        <p>
          <name>3._WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
      </A>
      <A>
        <id>wert</id>
        <typ>EIN_BESTIMMTER_TYP</typ>
        <date>wert</date>
        <p>
          <name>3._WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
        <p>
          <name>1._WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
        <p>
          <name>2._WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
        <p>
          <name>UNWICHTIGER_WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
        <p>
          <name>UNWICHTIGER_WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
      </A>
    </ROOT>
    Von den <A>-Elementen gibt es sehr viele. Mein Problem ist nun, dass die Reihenfolge und sogar Anzahl der <p>-Elemente innerhalb eines <A>-Elements variieren kann. Für meine tabellarische Ausgabe interessieren mich pro <A> immer nur die Werte zu <id>, <typ>, <date> und <value> der 3 zugehörigen <p>-Kinder (also 1., 2. und 3. WERT_AUS_WERTEVORRAT in dieser Reihenfolge). Mir fehlt ein Ansatz, wie ich die <value>-Elemente in der korrekten Reihenfolge in einer Tabelle darstellen lassen kann. Momentan stehen sie eben in der falschen Spalte, wenn das Schema nicht mit den ersten beiden <A>-Elementen übereinstimmt.

    Hat jemand eine Idee, wie ich das bewerkstelligen kann?

  • #2
    Du wirst die Namen und die Reihenfolge, die du haben willst, irgendwo definieren müssen, mit XSLT 2.0 einfach als Sequenz von Zeichenketten, mit XSLT 1.0 in einem separatem XML-Dokument oder im XSLT-Stylesheet.
    Hier ist ein Beispiel mit XSLT 2.0:
    Code:
    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="xs"
      version="2.0">
      
      <xsl:param name="col-names" as="xs:string+"
        select="('1._WERT_AUS_WERTEVORRAT',
                 '2._WERT_AUS_WERTEVORRAT',
                 '3._WERT_AUS_WERTEVORRAT')"/>
      
      <xsl:output method="html" indent="yes"/>
      
      <xsl:key name="k1" match="A/p" use="name"/>
    
      
      <xsl:template match="ROOT">
        <table>
          <thead>
            <tr>
              <xsl:for-each select="$col-names">
                <th><xsl:value-of select="."/></th>
              </xsl:for-each>
            </tr>
          </thead>
          <tbody>
            <xsl:for-each select="A">
              <xsl:variable name="row" as="element(A)" select="."/>
              <tr>
                <xsl:for-each select="$col-names">
                  <td><xsl:value-of select="key('k1', ., $row)/value"/></td>
                </xsl:for-each>
              </tr>
            </xsl:for-each>
          </tbody>
        </table>
      </xsl:template>
    
    </xsl:stylesheet>
    XSLT 2.0 kann man u.a. mit Saxon 9 oder mit AltovaXML Tools oder mit XQSharp ausführen.

    Mit XSLT 1.0 ist es umständlicher:
    Code:
    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:data="http://example.com/data"
      exclude-result-prefixes="data"
      version="1.0">
      
      <xsl:output method="html" indent="yes"/>
      
      <xsl:key name="k1" match="A/p" use="concat(generate-id(parent::A), '|', name)"/>
      
      <data:col-order xmlns="">
        <col-name>1._WERT_AUS_WERTEVORRAT</col-name>
        <col-name>2._WERT_AUS_WERTEVORRAT</col-name>
        <col-name>3._WERT_AUS_WERTEVORRAT</col-name>
      </data:col-order>
      
      <xsl:template match="ROOT">
        <xsl:variable name="col-names" select="document('')/xsl:stylesheet/data:col-order/col-name"/>
        <table>
          <thead>
            <tr>
              <xsl:for-each select="$col-names">
                <th><xsl:value-of select="."/></th>
              </xsl:for-each>
            </tr>
          </thead>
          <tbody>
            <xsl:for-each select="A">
              <xsl:variable name="row" select="."/>
              <tr>
                <xsl:for-each select="$col-names">
                  <xsl:variable name="col-name" select="."/>
                  <td>
                    <!-- need to change context node for key function -->
                    <xsl:for-each select="$row">
                      <xsl:value-of select="key('k1', concat(generate-id(.), '|', $col-name))/value"/>
                    </xsl:for-each>
                  </td>
                </xsl:for-each>
              </tr>
            </xsl:for-each>
          </tbody>
        </table>
      </xsl:template>
    
    </xsl:stylesheet>
    Beide Stylesheets machen aus
    Code:
    <ROOT>
      <A>
        <id>wert</id>
        <typ>EIN_BESTIMMTER_TYP</typ>
        <date>wert</date>
        <p>
          <name>1._WERT_AUS_WERTEVORRAT</name>
          <value>wert 1</value>
        </p>
        <p>
          <name>2._WERT_AUS_WERTEVORRAT</name>
          <value>wert 2</value>
        </p>
        <p>
          <name>3._WERT_AUS_WERTEVORRAT</name>
          <value>wert 3</value>
        </p>
      </A>
      <A>
        <id>wert</id>
        <typ>EIN_BESTIMMTER_TYP</typ>
        <date>wert</date>
        <p>
          <name>1._WERT_AUS_WERTEVORRAT</name>
          <value>wert 1</value>
        </p>
        <p>
          <name>2._WERT_AUS_WERTEVORRAT</name>
          <value>wert 2</value>
        </p>
        <p>
          <name>3._WERT_AUS_WERTEVORRAT</name>
          <value>wert 3</value>
        </p>
      </A>
      <A>
        <id>wert</id>
        <typ>EIN_BESTIMMTER_TYP</typ>
        <date>wert</date>
        <p>
          <name>3._WERT_AUS_WERTEVORRAT</name>
          <value>wert 3</value>
        </p>
        <p>
          <name>1._WERT_AUS_WERTEVORRAT</name>
          <value>wert 1</value>
        </p>
        <p>
          <name>2._WERT_AUS_WERTEVORRAT</name>
          <value>wert 2</value>
        </p>
        <p>
          <name>UNWICHTIGER_WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
        <p>
          <name>UNWICHTIGER_WERT_AUS_WERTEVORRAT</name>
          <value>wert</value>
        </p>
      </A>
    </ROOT>
    folgendes HTML-Fragment:
    Code:
    <table>
       <thead>
          <tr>
             <th>1._WERT_AUS_WERTEVORRAT</th>
             <th>2._WERT_AUS_WERTEVORRAT</th>
             <th>3._WERT_AUS_WERTEVORRAT</th>
          </tr>
       </thead>
       <tbody>
          <tr>
             <td>wert 1</td>
             <td>wert 2</td>
             <td>wert 3</td>
          </tr>
          <tr>
             <td>wert 1</td>
             <td>wert 2</td>
             <td>wert 3</td>
          </tr>
          <tr>
             <td>wert 1</td>
             <td>wert 2</td>
             <td>wert 3</td>
          </tr>
       </tbody>
    </table>

    Comment


    • #3
      Hallo, Martin!

      Wow, allerbesten Dank für Deine ausführliche Antwort!

      Ich konnte den Code Deines XSLT-1.0-Beispiels nun für das genaue Szenario anpassen und es funktioniert jetzt völlig problemlos! Ich werde mich in den nächsten Tagen noch weiter intensiv mit XSLT beschäftigen, da ich das grundlegende Verfahren Deiner Lösung zwar - glaube ich - schon ganz gut nachvollziehen kann, aber mit meinem bisherigen Wissen längst nicht darauf gekommen wäre.

      Vielen Dank nochmal!

      Comment

      Working...
      X