Announcement

Collapse
No announcement yet.

Rekursives Parsen - Ansatz gesucht

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

  • Rekursives Parsen - Ansatz gesucht

    Hallo,

    ich habe wieder einmal ein xslt - Problem.
    Ich möchte folgende XML - Datei 'serialisieren', d.h. in eine Struktur bringen, die man dann zeilenweise weiterverarbeiten kann.

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <methodResponse>
    
    <params>
    <param><value><struct>
    
    <member>
    <name>TIMESTAMP</name>
    <value>2001-01-01 10:10:10 +0200</value>
    </member>
    
    <member>
    <name>DATA</name>
    
    <value><array><data>
    
    <value><array><data>
    <value>D71_XX-XX_XX</value>
    <value>0</value>
    <value>33,33</value>
    </data></array></value>
    
    <value><array><data>
    <value>D21_XX-XX_XX</value>
    <value>0</value>
    <value>778888</value>
    </data></array></value>
    
    
    </data></array></value>
    
    </member>
    
    <member>
    <name>RESULT</name>
    <value>OK</value>
    </member>
    
    </struct></value></param>
    </params>
    
    </methodResponse>
    Im Ergebnis möchte ich etwas in der Art erhalten:
    Code:
    TIMESTAMP;2001-01-01 10:10:10 +0200;
    DATA;D71_XX-XX_XX;0;33,33;
    DATA;D21_XX-XX_XX;0;778888;
    RESULT;OK;
    Ich habe dazu bereits das:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" indent="yes" />
    <xsl:strip-space elements="*" />
    
    <xsl:template match="/">
      <xsl:apply-templates select="member" />
    </xsl:template>
    
    <xsl:template match="member">
      <xsl:variable name="mb" select="name" />
       <xsl:choose>
          <xsl:when test="$mb = 'DATA'">
    	 <xsl:apply-templates select="value" mode="data"/>
          </xsl:when>
          <xsl:when test="$mb = 'RESULT'">
             <xsl:text/>RESULT;<xsl:text/>
             <xsl:value-of select="value" />
             <xsl:text/>;&#xD;&#xA;<xsl:text/>
          </xsl:when>
          <xsl:when test="$mb = 'TIMESTAMP'">
             <xsl:text/>TIMESTAMP;<xsl:text/>
             <xsl:value-of select="value" />
             <xsl:text/>;&#xD;&#xA;<xsl:text/>
          </xsl:when>
       </xsl:choose>
    </xsl:template>
    
    
    <xsl:template match="data" mode="data">
      <xsl:text/>DATEN;<xsl:text/> 
      <xsl:for-each select="value">
         <xsl:value-of select="." /><xsl:text/>;<xsl:text/>
      </xsl:for-each>
      <xsl:text/>;&#xD;&#xA;<xsl:text/>
    </xsl:template>
    
    </xsl:stylesheet>
    Mein Problem sind die verschachtelten arrays im Member DATA.
    Abgebildet ist quasi ein Array von Arrays, die schließlich immer <values> in einer definierten Reihenfolge enthalten.
    Gefühlt ist mein "Einstieg" mit <xsl:template match="data"> zu weit 'oben'.

    Wie komme ich am besten an die ganz 'inneren' Arrays heran?
    Die Struktur ist immer nur 2stufig - also 'ein Array in einem Array'. Trotzdem gibt es doch bestimmt eine elegante Lösung, die immer das innerste Array liefert, egal wie verschachtelt die Daten kommen.

    Wenn ich das Array dann habe, wäre der <for-each> - Ansatz für die Weiterverarbeitung richtig?

    Danke für Hinweise!

    Tino
    Ich habs gleich!
    ... sagte der Programmierer.

  • #2
    So, ich bin etwas weiter:


    Code:
    ....
    
    <xsl:template match="data">
      <xsl:apply-templates select="value/array"/>
      <xsl:apply-templates select="." mode="data"/>
    </xsl:template>
    
    <xsl:template match="data" mode="data">
      <xsl:text/>DATEN;<xsl:text/> 
      <xsl:for-each select="value">
         <xsl:value-of select="." /><xsl:text/>;<xsl:text/>
      </xsl:for-each>
      <xsl:text/>;&#xD;&#xA;<xsl:text/>
    </xsl:template>
    Liefert immerhin

    Code:
    TIMESTAMP;2001-01-01 10:10:10 +0200;
    DATEN;D71_XX-XX_XX;0;33,33;;
    DATEN;D21_XX-XX_XX;0;778888;;
    DATEN;D71_XX-XX_XX033,33;D21_XX-XX_XX0778888;;
    RESULT;OK;
    Allerdings ist die kursiv markierte Zeile noch zuviel. Ich vermute, die kommt vom "äußeren" Durchlauf ( <xsl:apply-templates select="value/array"/> ).
    Wie kann man das noch unterdrücken?

    Danke
    Tino
    Ich habs gleich!
    ... sagte der Programmierer.

    Comment


    • #3
      Weiter im Monolog .. mit einer (suboptimalen?) Lösung

      Die folgende Transformation liefert das gewünschte Ergebnis, erscheint mir (trotz gefundenem if..then..else ) aber etwas 'umständlich'.
      Vielleicht hat noch jemand einen optimierenden Hinweis.

      Vielen Dank.

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

      <xsl:template match="/">
          <xsl:apply-templates select="member" />
      </xsl:template>



      <xsl:template match="member">
          <xsl:variable name="mb" select="name" />
          <xsl:choose>
              <xsl:when test="$mb = 'DATA'">
                  <xsl:apply-templates select="value" />
              </xsl:when>
              <xsl:when test="$mb = 'RESULT'">
                  <xsl:text/>RESULT;<xsl:text/>
                  <xsl:value-of select="value" />
                  <xsl:text>&#xD;&#xA;</xsl:text>
              </xsl:when>
              <xsl:when test="$mb = 'TIMESTAMP'">
                  <xsl:text/>TIMESTAMP;<xsl:text/>
                  <xsl:value-of select="value" />
                  <xsl:text>&#xD;&#xA;</xsl:text>
                    </xsl:when>
          </xsl:choose>
      </xsl:template>

      <xsl:template match="data">
          <xsl:variable name="arr" select="count(value/array)" />
          <xsl:choose>
                <xsl:when test="$arr>0">
                  <xsl:apply-templates select="value" />
              </xsl:when>
              <xsl:otherwise>
                  <xsl:apply-templates select="." mode="data"/>
              </xsl:otherwise>
          </xsl:choose>
      </xsl:template>

      <xsl:template match="data" mode="data">
          <xsl:text>DATA;</xsl:text> 
          <xsl:for-each select="value">
              <xsl:value-of select="." />
              <xsl:text>;</xsl:text>
          </xsl:for-each>
          <xsl:text>&#xD;&#xA;</xsl:text>
      </xsl:template>



      </xsl:stylesheet>
      Ich habs gleich!
      ... sagte der Programmierer.

      Comment

      Working...
      X