Announcement

Collapse
No announcement yet.

Umwandlung von einer flachen xml Struktur in html Listen Elemente ul bzw. li

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

  • Umwandlung von einer flachen xml Struktur in html Listen Elemente ul bzw. li

    Hallo,

    hab ein Problem mit der Umwandlung von einer flachen xml Struktur in html Listen Elemente ul bzw. li.
    Ich hab ein Beispiel im Internet gefunden, dass ich adaptiert habe und das auch funktioniert. Nur leider hab ich jetzt festgestellt, das der Output nicht xhtml transitional konform ist.
    Hier ein Beispiel Input:
    HTML Code:
    ...
    		<kom>irgend ein text <f>fetter text</f> irgend ein text <k>kursiver text</k></kom>
    		<kom ty="aufz" eb="1">Das ist der erste Punkt</kom>
    		<kom ty="aufz" eb="1">Das ist der zweite Punkt</kom>
    		<kom ty="aufz" eb="2">Das ist der erste Punkt der <f>zweiten</f> Ebene</kom>
    		<kom ty="aufz" eb="3">Das ist der erste Punkt der <f>dritten</f> Ebene</kom>
    		<kom ty="aufz" eb="1">Das ist der dritte Punkt</kom>
    		<kom ty="aufz" eb="1">Das ist der vierte Punkt</kom>
    		<kom ty="oNr">irgend ein text <f>fetter text</f> irgend ein text <k>kursiver text</k></kom>
    ...
    Das xsl das dies derzeit konvertiert:
    HTML Code:
    .....
    <xsl:template match="kom">
    	<xsl:choose>
    		<xsl:when test="@ty='aufz' or @ty='aufz_num'">
    			<xsl:apply-templates />
    		</xsl:when>
    	  
    		<xsl:otherwise>
    			<p class="content">
    				<xsl:apply-templates />
    			</p>
    		</xsl:otherwise>
    	</xsl:choose>
    </xsl:template>
    .....	
     <xsl:key name='listitems1_ul' match="kom[@eb='1' and preceding-sibling::kom[1][@eb='1' or @eb='2' or @eb='3'] and @ty='aufz']"
        use="generate-id(preceding-sibling::kom[@eb='1'][1])"/>
     
     <xsl:key name='listitems2_ul' match="kom[@eb='2' and preceding-sibling::kom[1][@eb='2' or @eb='3'] and @ty='aufz']"
        use="generate-id(preceding-sibling::kom[@eb='2' and preceding-sibling::kom[1][@eb='1']][1])"/>
     
     <xsl:key name='listitems3_ul' match="kom[@eb='3' and preceding-sibling::kom[1][@eb='3'] and @ty='aufz']"
        use="generate-id(preceding-sibling::kom[@eb='3' and preceding-sibling::kom[1][@eb='2']][1])"/>
     
     <!--First Items in sublists-->
     <xsl:key name='sublistitems2_ul' match="kom[@eb='2' and preceding-sibling::kom[1][@eb='1'] and @ty='aufz']"
        use="generate-id(preceding-sibling::kom[@eb='1'][1])"/>
     
     <xsl:key name='sublistitems3_ul' match="kom[@eb='3' and preceding-sibling::kom[1][@eb='2'] and @ty='aufz']"
        use="generate-id(preceding-sibling::kom[@eb='2'][1])"/>
     
     <!--Process Level 1 Lists-->
     <xsl:template match="kom[@eb='1' and @ty='aufz']" mode="startlist_ul">
    	 <xsl:apply-templates select="." mode="Items_ul"/>
    	 <xsl:apply-templates select="key('sublistitems2_ul', generate-id())"
    	 mode="openlist_ul"/>
    	 <xsl:apply-templates select="key('listitems1_ul', generate-id())"
    	 mode="startlist_ul"/>
     </xsl:template>
     
     <!--Process Level 2 Lists-->
     <xsl:template match="kom[@eb='2' and @ty='aufz']" mode="startlist_ul">
    	  <xsl:apply-templates select="." mode="Items_ul"/>
    	  <xsl:apply-templates select="key('sublistitems3_ul', generate-id())"
    	 mode="openlist_ul"/>
    	  <xsl:apply-templates select="key('listitems2_ul', generate-id())"
    	 mode="startlist_ul"/>
     </xsl:template>
     
     <!--Process Level 3 Lists-->
     <xsl:template match="kom[@eb='3' and @ty='aufz']" mode="startlist_ul">
    	  <xsl:apply-templates select="." mode="Items_ul"/>
    	  <xsl:apply-templates select="key('listitems3_ul', generate-id())"
    	 mode="startlist_ul"/>
     </xsl:template>
      
     <!--Start a list if the contents is not empty-->
     <xsl:template match="kom[(@eb='1' or @eb='2' or @eb='3') and @ty='aufz']" mode="openlist_ul">
    	 <xsl:if test="string(.)!=''">
    	 
    	 <ul>
     		<xsl:if test="@code">
    			<xsl:attribute name="code"><xsl:value-of select="@code"/></xsl:attribute>
    		</xsl:if>
    		<xsl:if test="@type">
    			<xsl:attribute name="type"><xsl:value-of select="@type"/></xsl:attribute>
    		</xsl:if>
    	<xsl:apply-templates select="." mode="startlist_ul"/>
    	</ul>
    	
    	</xsl:if>
     </xsl:template>
     
     <!--Output Individual List Items-->
     <xsl:template match="kom[(@eb='1' or @eb='2' or @eb='3') and @ty='aufz']" mode="Items_ul">
    	<xsl:if test="string(.)!=''">
    		<li>
    			<xsl:copy-of select="node()"/>
    		</li>
    	</xsl:if>
     </xsl:template>
      
     <!--Pick out the first level 1 item in a list, dump other items -->
     <xsl:template match="kom[(@eb='1' or @eb='2' or @eb='3') and @ty='aufz']" >
    	<xsl:if test="@eb='1' and @ty='aufz' and not (preceding-sibling::kom[1][@eb='1' or @eb='2' or @eb='3'])">
    	<ul>
      		<xsl:if test="@code">
    			<xsl:attribute name="code"><xsl:value-of select="@code"/></xsl:attribute>
    		</xsl:if>
    		<xsl:if test="@type">
    			<xsl:attribute name="type"><xsl:value-of select="@type"/></xsl:attribute>
    		</xsl:if>
    	<xsl:apply-templates select="." mode="startlist_ul"/>
    	</ul>
    	</xsl:if>
     </xsl:template>
    .....
    Das ist der derzeitige Output:

    HTML Code:
    <p class="content">irgend ein text <f>fetter text</f> irgend ein text <k>kursiver text</k></p>
    <ul>
    	<li>Das ist der erste Punkt</li>
    	<li>Das ist der zweite Punkt</li>
    	<ul>
    		<li>Das ist der erste Punkt der <f>zweiten</f> Ebene</li>
    			<ul>
    				<li>Das ist der erste Punkt der <f>dritten</f> Ebene</li>
    			</ul>
    	</ul>
    	<li>Das ist der dritte Punkt</li>
    	<li>Das ist der vierte Punkt</li>
    </ul>
    <p class="content">irgend ein text <f>fetter text</f> irgend ein text <k>kursiver text</k></p>
    Dieser ist leider nicht xhtml transitional konform, weil zB das zweite li Element geschlossen wird.

    Kann mir jemand sagen, was ich an dem Beispiel andern muss um xhtml transitional Konformität zu erhalten?
    Danke.
    Halmarius

  • #2
    Hast du mal darüber nachgedacht, dass Problem in XSLT 2.0 (mit einem XSLT 2.0 Prozessor wie Saxon 9 (http://saxon.sourceforge.net) oder AltovaXML (http://www.altova.com/altovaxml.html)) zu lösen?
    Damit sieht das so aus:
    Code:
    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:mf="http://example.com/mf"
      xmlns="http://www.w3.org/1999/xhtml"
      exclude-result-prefixes="xs mf"
      version="2.0">
      
      <xsl:output method="xhtml" indent="yes"/>
      
      <xsl:function name="mf:group" as="node()*">
        <xsl:param name="elements" as="element(kom)*"/>
        <xsl:param name="level" as="xs:integer"/>
        <xsl:if test="$elements">
          <ul>
            <xsl:for-each-group select="$elements" group-starting-with="kom[@eb = $level]">
              <li>
                <xsl:apply-templates/>
                <xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
              </li>
            </xsl:for-each-group>
          </ul>
        </xsl:if>
      </xsl:function>
      
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* , node()"/>
        </xsl:copy>
      </xsl:template>
      
      <xsl:template match="root">
        <div>
          <xsl:for-each-group select="*" group-adjacent="@ty = 'aufz' and @eb">
            <xsl:choose>
              <xsl:when test="current-grouping-key()">
                <xsl:sequence select="mf:group(current-group(), 1)"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:apply-templates select="current-group()"/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:for-each-group>
        </div>
      </xsl:template>
      
      <xsl:template match="kom[not(@ty = 'aufz')]">
        <p class="content">
          <xsl:apply-templates/>
        </p>
      </xsl:template>
      
      <xsl:template match="f">
        <b>
          <xsl:apply-templates/>
        </b>
      </xsl:template>
      
      <xsl:template match="k">
        <i>
          <xsl:apply-templates/>
        </i>
      </xsl:template>
      
    </xsl:stylesheet>
    und macht aus
    Code:
    <root>
    		<kom>irgend ein text <f>fetter text</f> irgend ein text <k>kursiver text</k></kom>
    		<kom ty="aufz" eb="1">Das ist der erste Punkt</kom>
    		<kom ty="aufz" eb="1">Das ist der zweite Punkt</kom>
    		<kom ty="aufz" eb="2">Das ist der erste Punkt der <f>zweiten</f> Ebene</kom>
    		<kom ty="aufz" eb="3">Das ist der erste Punkt der <f>dritten</f> Ebene</kom>
    		<kom ty="aufz" eb="1">Das ist der dritte Punkt</kom>
    		<kom ty="aufz" eb="1">Das ist der vierte Punkt</kom>
    		<kom ty="oNr">irgend ein text <f>fetter text</f> irgend ein text <k>kursiver text</k></kom>
    </root>
    das Resultat:
    Code:
    <div xmlns="http://www.w3.org/1999/xhtml">
       <p class="content">irgend ein text <b>fetter text</b> irgend ein text <i>kursiver text</i></p>
       <ul>
          <li>Das ist der erste Punkt</li>
          <li>Das ist der zweite Punkt
             <ul>
                <li>Das ist der erste Punkt der <b>zweiten</b> Ebene
                   <ul>
                      <li>Das ist der erste Punkt der <b>dritten</b> Ebene
                      </li>
                   </ul>
                </li>
             </ul>
          </li>
          <li>Das ist der dritte Punkt</li>
          <li>Das ist der vierte Punkt</li>
       </ul>
       <p class="content">irgend ein text <b>fetter text</b> irgend ein text <i>kursiver text</i></p>
    </div>
    Lass uns mal wissen, ob XSLT 2.0 eine Option für dich ist, damit sind Lösungen kürzer, verständlicher, wartbarer und effizienter als mit XSLT 1.0.

    Comment


    • #3
      Hallo,

      Danke für den Beispiel-Code und die Hinweise.
      Hab es bei mir für das kleine Beispiel ausprobiert und es hat funktioniert.
      Dieses kleine Beispiel ist allerdings nur ein kleiner Ausschnitte aus komplexeren xml Daten. Sobald ich den Beispiel-Code darauf anwendet funkt es nicht mehr. Leider hab ich derzeit nicht die Kapazität großartige Veränderungen zu machen.
      Wir verwenden derzeit ein anderes xsl Script (Kurzfassung des Scripts im Anhang), welches aber mit der Konvertierung von Listen nichts am Hut hat. Leider ist es mir nicht gelungen den Beispiel-Code auf die Schnelle in dieses xsl Script zu intergrieren.
      Beispiel-Daten sind ebenfalls in Anhang.
      Wir verwenden derzeit den saxon9.
      Bin für jeden Hinweis dankbar.
      Danke.

      Grüße
      Halmarius
      Attached Files

      Comment

      Working...
      X