tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
4
ZUGRIFFE
1593
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    halmarius halmarius ist offline Grünschnabel
    Registriert seit
    Apr 2007
    Beiträge
    3
    Hallo,

    hab ein Problem mit der Umwandlung von einer flachen xml Struktur in html Listen Elemente ul bzw. li.
    Ich hab ein xsl 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>
    .....
    HTML-Code:
    <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. #2
    Avatar von hela
    hela hela ist offline Mitglied Smaragd
    tutorials.de Premium-User
    Registriert seit
    Oct 2004
    Beiträge
    1.123
    Hallo,

    ich habe dein XML etwas schlanker gemacht und angenommen es sieht so aus:
    Code xml:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    <root>
        <item level="1">Punkt 1</item>
        <item level="1">Punkt 2</item>
        <item level="2">Punkt 2.1</item>
        <item level="3">Punkt 2.1.1</item>
        <item level="4">Punkt 2.1.1.1</item>
        <item level="3">Punkt 2.1.2</item>
        <item level="2">Punkt 2.2</item>
        <item level="3">Punkt 2.2.1</item>
        <item level="2">Punkt 2.3</item>
        <item level="1">Punkt 3</item>
        <item level="1">Punkt 4</item>
    </root>
    Zu jedem item-Knoten kannst du mit einem entsprechenden Schlüssel die folgenden Knoten mit tieferer Ebene finden. Wenn also ein Knoten Folgeknoten mit tieferer Ebene hat, dann öffnest du ein neues UL-Element innerhalb des aktuellen LI-Elements:
    Code xml:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     
        <xsl:output method="html"
            doctype-system="about:legacy-compat"
            media-type="text/html"
            encoding="UTF-8"
            omit-xml-declaration="yes"
            indent="yes"
        />
     
        <!-- Nachfolgende item-Knoten in tieferer Ebene finden -->
        <xsl:key
            name="next-levels"
            match="item[@level='4']"
            use="generate-id(preceding-sibling::item[@level='1' or @level='2' or @level='3'][1])" />
        <xsl:key
            name="next-levels"
            match="item[@level='3']"
            use="generate-id(preceding-sibling::item[@level='1' or @level='2'][1])" />
        <xsl:key
            name="next-levels"
            match="item[@level='2']"
            use="generate-id(preceding-sibling::item[@level='1'][1])" />
     
        <xsl:template match="/root">
            <html>
                <head>
                    <title>Test</title>
                </head>
                <body>
                    <ul>
                        <!-- item-Knoten der obersten Ebene übergeben: -->
                        <xsl:apply-templates select="item[@level='1']" />
                    </ul>
                </body>
            </html>
        </xsl:template>
     
        <xsl:template match="item">
            <li>
                <xsl:value-of select="." />
                <!-- Gibt es nachfolgende Knoten in tieferer Ebene? -->
                <xsl:if test="count(key('next-levels',generate-id()))">
                    <ul>
                        <!-- Nachfolgende Knoten in tieferer Ebene übergeben: -->
                        <xsl:apply-templates select="key('next-levels',generate-id())" />
                    </ul>
                </xsl:if>
            </li>
        </xsl:template>
     
    </xsl:stylesheet>
    Das war's schon.
    Geändert von hela (31.10.11 um 23:29 Uhr)
     

  3. #3
    halmarius halmarius ist offline Grünschnabel
    Registriert seit
    Apr 2007
    Beiträge
    3
    Danke für das Beispiel. Ich hab versucht es für meine Bedingungen anzupassen:

    HTML-Code:
        <xsl:key
            name="next-levels"
            match="kom[@ty='aufz' and @eb='3']"
            use="generate-id(preceding-sibling::kom[(@ty='aufz' and @eb='1') or (@ty='aufz' and @eb='2')][1])" />
        <xsl:key
            name="next-levels"
            match="kom[@ty='aufz' and @eb='2']"
            use="generate-id(preceding-sibling::kom[@ty='aufz' and @eb='1'][1])" />
     
    	<xsl:template match="kom[@ty='aufz' and @eb='1']">
    		<ul>
    			<xsl:apply-templates select="kom[@ty='aufz' and @eb='1']" />
    		</ul>
    	</xsl:template>
     
    	<xsl:template match="kom[@ty='aufz' and @eb>0]" >
    			<li>
    				<xsl:value-of select="." />
    				<xsl:if test="count(key('next-levels',generate-id()))">
    					<ul>
    						<xsl:apply-templates select="key('next-levels',generate-id())" />
    					</ul>
    				</xsl:if>
    			</li>
    	</xsl:template>
    Als Ergebnis kam die Meldung:
    HTML-Code:
    Ambiguous rule match for...
    Was mir auch nachvollziehbar ist.

    Das Ergebnis war wie folgt:

    HTML-Code:
    <p class="content">irgend ein text <f>fetter text</f> irgend ein text <k>kursiver text</k></p>
    <li>Das ist der erste Punkt</li>
    <li>Das ist der zweite Punkt
    	<ul>
    		<li>Das ist der erste Punkt der zweiten Ebene</li>
    	</ul>
    </li>
    <li>Das ist der erste Punkt der zweiten Ebene</li>
    <li>Das ist der dritte Punkt</li>
    <li>Das ist der vierte Punkt</li>
    <p class="content">irgend ein text <f>fetter text</f> irgend ein text <k>kursiver text</k></p>
    Was mir darin auffällt:
    • die f-Elementnamen innerhalb der li-Elemente fehlen und
    • der erste Punkt der zweiten Ebene ist doppelt vorhanden

    Bin für jeden Hinweis dankbar.

    Grüße
    Halmarius
     

  4. #4
    Avatar von hela
    hela hela ist offline Mitglied Smaragd
    tutorials.de Premium-User
    Registriert seit
    Oct 2004
    Beiträge
    1.123
    Hallo,

    wenn du in den KOM-Knoten noch Kindelemente hast, die du unverändert weiterverwenden möchtest, dann brauchst du nur den Knoteninhalt mit dem COPY-OF-Element als Inhalt des LI-Elements in den Ausgabebaum kopieren.
    Statt
    Code xml:
    1
    
    <xsl:value-of select="." />
    müsstest du dann folgendes notieren
    Code xml:
    1
    
    <xsl:copy-of select="node()" />

    Ansonsten müsste man ein "Identity Copy" verwenden, um z.B. den Elementnamen zu ändern:
    Code xml:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     
      <xsl:output method="xml" indent="yes" encoding="UTF-8" />
     
      <xsl:key
        name="next-levels"
        match="kom[@ty='aufz' and @eb='3']"
        use="generate-id(preceding-sibling::kom[@ty='aufz' and (@eb='1' or @eb='2')][1])" />
      <xsl:key
        name="next-levels"
        match="kom[@ty='aufz' and @eb='2']"
        use="generate-id(preceding-sibling::kom[@ty='aufz' and @eb='1'][1])" />
     
      <xsl:template match="/root">
        <ul>
          <xsl:apply-templates select="kom[@ty='aufz' and @eb='1']" />
        </ul>
      </xsl:template>
     
      <xsl:template match="kom" >
        <li>
          <xsl:apply-templates select="node()" mode="icopy" />
          <xsl:if test="key('next-levels',generate-id())">
            <ul>
              <xsl:apply-templates select="key('next-levels',generate-id())" />
            </ul>
          </xsl:if>
        </li>
      </xsl:template>
     
      <xsl:template match="@*|node()" mode="icopy">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()" mode="icopy" />
        </xsl:copy>  
      </xsl:template>
     
      <xsl:template match="f" mode="icopy">
        <b>
          <xsl:apply-templates select="@*|node()" mode="icopy" />
        </b>
      </xsl:template>
     
    </xsl:stylesheet>
    Damit kann ich das XML-Quelldokument
    Code xml:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    <?xml version="1.0" encoding="UTF-8"?>
    <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 class="fett">zweiten</f> Ebene</kom>
            <kom ty="aufz" eb="3">Das ist der erste Punkt der <f class="fett">dritten</f> Ebene</kom>
            <kom ty="aufz" eb="1">Das ist der dritte Punkt: H<sub>2</sub>SO<sub>4</sub></kom>
            <kom ty="aufz" eb="1">Das ist der vierte Punkt: E = m·c<sup>2</sup></kom>
            <kom ty="oNr">irgend ein text <f>fetter text</f> irgend ein text <k>kursiver text</k></kom>
    </root>
    ... in diese Ausgabe transformieren:
    Code xml:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    <?xml version="1.0" encoding="UTF-8"?>
    <ul>
      <li>Das ist der erste Punkt</li>
      <li>Das ist der zweite Punkt
        <ul>
          <li>Das ist der erste Punkt der <b class="fett">zweiten</b> Ebene
            <ul>
              <li>Das ist der erste Punkt der <b class="fett">dritten</b> Ebene</li>
            </ul>
          </li>
        </ul>
      </li>
      <li>Das ist der dritte Punkt: H<sub>2</sub>SO<sub>4</sub></li>
      <li>Das ist der vierte Punkt: E = m·c<sup>2</sup></li>
    </ul>
    Ich habe das mit "libxslt" transformiert, was anderes steht mir im Augenblick nicht zur Verfügung.
     

  5. #5
    halmarius halmarius ist offline Grünschnabel
    Registriert seit
    Apr 2007
    Beiträge
    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. Hat offenbar etwas mit dem "Einstiegspunkt" zu tun.
    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
    Angehängte Dateien Angehängte Dateien
     

Ähnliche Themen

  1. elemente von 2 listen vergleichen
    Von javama im Forum Java
    Antworten: 6
    Letzter Beitrag: 11.05.11, 13:00
  2. Antworten: 4
    Letzter Beitrag: 21.02.10, 00:02
  3. Antworten: 13
    Letzter Beitrag: 16.04.09, 21:52
  4. Umwandlung von xml auf html mit sax, jdom
    Von _logger im Forum Java
    Antworten: 1
    Letzter Beitrag: 03.11.07, 13:48
  5. OnClick Event und Listen Elemente
    Von olqs im Forum Javascript & Ajax
    Antworten: 2
    Letzter Beitrag: 25.09.07, 13:16

Stichworte