xslt: Strings, die nicht in Tags eingegliedert ist

meci

Grünschnabel
[XSLT] Strings, die nicht in Tags eingegliedert sind

Hallo!

Ich habe folgende XML-Dateistruktur vorliegen:
Code:
<xml>
  <tag1>
  ...
  </tag1>
    String1
    <br>
    String2 
  <tag 2>
   ... 
  </tag2>
</xml>

Als erstes habe ich versucht, die Daten aus <tag2> herauszubekommen. Das funktioniert soweit ganz gut, allerdings sind neben den <tag2>-Daten auch String 1 und String 2 (die nicht in Tags eingegliedert sind) in der transformierten XML-Datei enthalten, was vermieden werden soll.

Abgesehen davon, dass die beiden Strings bei der <tag2>-Transformation stören - wie komme ich an String 1 und String 2 mittels XSLT-Transformation zwecks Weiterverarbeitung ran?

Vielen Dank für die Hilfe!
 
Zuletzt bearbeitet:
Hi.
Ich habe folgende XML-Dateistruktur vorliegen:
Code:
<xml>
  <tag1>
  ...
  </tag1>
    String1
    <br>
    String2 
  <tag 2>
   ... 
  </tag2>
</xml>

Als erstes habe ich versucht, die Daten aus <tag2> herauszubekommen. Das funktioniert soweit ganz gut, allerdings sind neben den <tag2>-Daten auch String 1 und String 2 (die nicht in Tags eingegliedert sind) in der transformierten XML-Datei enthalten, was vermieden werden soll.
Jeder Text ist in XML in Tags eingegliedert, String 1 und String 2 sind Kindelemente des <xml> Elements.

Generell werden implizit alle Textknoten eines XML Dokumentes ausgegeben, wenn diese mit apply-templates verarbeitet werden. Entweder wählst du gleich das richtige Element mit dem select Attribut aus, oder du definierst templates für text() Knoten die keine Ausgabe erzeugen. Zeig dein XSL.
Abgesehen davon, dass die beiden Strings bei der <tag2>-Transformation stören - wie komme ich an String 1 und String 2 mittels XSLT-Transformation zwecks Weiterverarbeitung ran?
Code:
xml/text()
Dieser XPath liefert alle Textknoten unterhalb des xml Elementes.

Gruß

PS: Dein XML Dokument ist nicht wohlgeformt.
 
Hallo!
Zeig dein XSL.

Code:
xml/text()
Dieser XPath liefert alle Textknoten unterhalb des xml Elementes.

Danke für deine Antwort!
Ich habe vorhin nur einen knappen Überblick gepostet, hier die genaue Struktur meiner XML-Ausgangsdatei und des XSLT-Stylesheets:

XML-Datei:
Code:
<?xml version="1.0" encoding="iso-8859-1"?>
<start>
  <overview>
    <p>String 1 
	  <br/>
        <img src="bild1.jpg" />
	  <br/>
        String 2 <br/>
       &nbsp;&nbsp; 
		String 3 <br/>
      <img src="bild2.jpg"/>
	  <br/>
      String 4
	  <br/>
      <anker>
        <link href="http://link1.com"/>
        Link 1
	  </anker>
      <br/>
      <anker>
        <link href="http://link2.com"/>
        Link2
	  </anker>
      <br/>
      <anker>
        <link href="http://link3.com"/>
        Link3
	  </anker>
      <br/>
      <anker>
	    <link href="http://link4.com"/>
         Link4
	  </anker>
	  <br/>
      <anker>
        <link href="http://link5.com"/>
        Link5
	  </anker>
      <br/>
    </p>
  </overview>
</start>

XSLT-Stylesheet
Code:
<xsl:stylesheet version = '1.0'
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>


<xsl:template match="anker">

  <moeglichkeit>   
               <link>
                 <xsl:value-of select="link/@href"/> 
              </link>
          <linktext>
          <xsl:value-of select="//anker"/>
          </linktext>

</moeglichkeit>
</xsl:template>


</xsl:stylesheet>

Jetzt merke ich gerade, dass - abgesehen vom rot-markierten &nbsp;, das ich manuell entfernen muss, damit der Parser durchläuft (-> weiß wer, wie ich die automatisch wegbekomme?), auch die Link-Adressen nicht stimmen (es wird immer Link1 ausgegeben).

Wenn ich die XML-Datei mit diesem XSLT-Stylesheet durchlaufen lasse, so kommt das raus:

Code:
<?xml version="1.0" encoding="UTF-16"?>
  
    String 1 
	  
        
	  
        String 2 
       
		String 3 
      
	  
      String 4
	  
      <moeglichkeit><link>http://link1.com</link><linktext>
        
        Link 1
	  </linktext></moeglichkeit>
      
      <moeglichkeit><link>http://link2.com</link><linktext>
        
        Link 1
	  </linktext></moeglichkeit>
      
      <moeglichkeit><link>http://link3.com</link><linktext>

        
        Link 1
	  </linktext></moeglichkeit>
      
      <moeglichkeit><link>http://link4.com</link><linktext>
        
        Link 1
	  </linktext></moeglichkeit>
	  
      <moeglichkeit><link>http://link5.com</link><linktext>
        
        Link 1
	  </linktext></moeglichkeit>

Jetzt steh' ich somit vor folgenden Problemen:

- Wie die &nbsp; automatisch entfernen?
- Wie die richtigen "Links" (Link1, Link2, usw..) rausbringen?
- Wie die die blau-markierten Strings (String1 - 4) in Tags einschließen?
(<string1>String 1</string1> <string2>String 2</string2> usw..)

Danke für's bis hierher-Durchlesen meines Problems, bin dankbar für jede Hilfe!
 
Hi.
Ich habe vorhin nur einen knappen Überblick gepostet, hier die genaue Struktur meiner XML-Ausgangsdatei und des XSLT-Stylesheets:
Warum nicht gleich so?
Jetzt merke ich gerade, dass - abgesehen vom rot-markierten &nbsp;, das ich manuell entfernen muss, damit der Parser durchläuft (-> weiß wer, wie ich die automatisch wegbekomme?), auch die Link-Adressen nicht stimmen (es wird immer Link1 ausgegeben).

Wenn ich die XML-Datei mit diesem XSLT-Stylesheet durchlaufen lasse, so kommt das raus:

Code:
<?xml version="1.0" encoding="UTF-16"?>
  
    String 1 
	  
        
	  
        String 2 
       
		String 3 
      
	  
      String 4
	  
      <moeglichkeit><link>http://link1.com</link><linktext>
        
        Link 1
	  </linktext></moeglichkeit>
      
      <moeglichkeit><link>http://link2.com</link><linktext>
        
        Link 1
	  </linktext></moeglichkeit>
      
      <moeglichkeit><link>http://link3.com</link><linktext>

        
        Link 1
	  </linktext></moeglichkeit>
      
      <moeglichkeit><link>http://link4.com</link><linktext>
        
        Link 1
	  </linktext></moeglichkeit>
	  
      <moeglichkeit><link>http://link5.com</link><linktext>
        
        Link 1
	  </linktext></moeglichkeit>

Jetzt steh' ich somit vor folgenden Problemen:

- Wie die &nbsp; automatisch entfernen?
Du mußt die Entität einfach im XML Dokument (bzw. in der DTD) definieren:
Code:
<!DOCTYPE start [
<!ENTITY nbsp " " ><!-- replace &nbsp; with Unicode character 0x00A0 -->
]>
- Wie die richtigen "Links" (Link1, Link2, usw..) rausbringen?
Mit dem XPath "//anker" wählst du alle Anker im Dokument aus. Du benötigst aber nur den Text des aktuellen Ankers (statt "//anker" einfach ".").
- Wie die die blau-markierten Strings (String1 - 4) in Tags einschließen?
(<string1>String 1</string1> <string2>String 2</string2> usw..)
Das könntest du mit for-each machen.

Bsp:
XML:
<xsl:for-each select="//overview/p/text()">
    <xsl:value-of select="." />
</xsl:for-each>
Gruß
 
Zuletzt bearbeitet von einem Moderator:
Mit dem XPath "//anker" wählst du alle Anker im Dokument aus. Du benötigst aber nur den Text des aktuellen Ankers (statt "//anker" einfach ".").
Stimmt, Danke!

Somit sieht mein Code jetzt so aus:

XML:
<xsl:stylesheet version = '1.0'
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>


<xsl:template match="anker">

  <moeglichkeit>   
               <link>
                 <xsl:value-of select="link/@href"/> 
              </link>
          <linktext>
          <xsl:value-of select="."/>
          </linktext>

</moeglichkeit>
</xsl:template>

</xsl:stylesheet>

Das könntest du mit for-each machen.

Bsp:
XML:
<xsl:for-each select="//overview/p/text()">
    <xsl:value-of select="." />
</xsl:for-each>
Gruß

Hmm, danke für den Hinweis, aber irgendwie lassen sich mein Code und deiner nicht verbinden. Es werden entweder nur die Strings geparst oder nur die <anker>.

Ich hab's auf diese Weise probiert: http://www.zvon.org/xxl/XSLTutorial/Output_ger/example72_ch2.html

Wo liege ich da falsch?

(Danke nochmal!)
 
Zuletzt bearbeitet von einem Moderator:
Keine Ahnung. Wie sieht dein Code aus? Wo hast du das for-each eingefügt?

Gruß

XML:
<xsl:stylesheet version = '1.0'
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:template match="overview">
   
      <xsl:for-each select="//overview/p/text()">
   
          <myString><xsl:value-of select="." /></myString>
   
      </xsl:for-each> 
</xsl:template>

<xsl:template match="anker">

  <moeglichkeit>   
               <link>
                 <xsl:value-of select="link/@href"/> 
              </link>
          <linktext>
          <xsl:value-of select="."/>
          </linktext>

</moeglichkeit>
</xsl:template>
</xsl:stylesheet>

Das führt zu:

XML:
<?xml version="1.0" encoding="UTF-16"?>
  <myString>String 1 
	  </myString><myString>
        </myString><myString>
	  </myString><myString>
        String 2 </myString><myString>
       </myString><myString>
		String 3 </myString><myString>
      </myString><myString>

	  </myString><myString>
      String 4
	  </myString><myString>
      </myString><myString>
      </myString><myString>
      </myString><myString>
      </myString><myString>
      </myString><myString>
      </myString><myString>

      </myString><myString>
	  </myString><myString>
      </myString><myString>
      </myString><myString>
    </myString>
Hier wird anscheinend jede Zeile mit <myString> </myString> geparst. Der Code, um die <anker> auszulesen, wird hier anscheinend "overruled"...

(Danke, noch immer und schon wieder!)
 
Zuletzt bearbeitet von einem Moderator:
Hier wird anscheinend jede Zeile mit <myString> </myString> geparst.
Nein, Zeilen spielen in XML keine Rolle. Es werden alle Textknoten, auch die die nur Leerzeichen enthalten, verarbeitet. Wenn du nur die Textknoten verarbeiten willst, die nicht nur aus Leerzeichen bestehen, mußt du die Knoten entsprechend filtern:
Code:
//overview/p/text()[normalize-space(.) != '']
Der Code, um die <anker> auszulesen, wird hier anscheinend "overruled"...
Ja, natürlich. Die <anker> liegen ja innerhalb von <overview>, welches du mit deinem "overview" Template verarbeitest. Wenn du dann innerhalb dieses Templates nicht nochmal explizit <xsl:apply-templates> aufrufst, werden unterhalb dieses Elements keine Templates mehr angewendet, denn sie wurden ja bereits verarbeitet...
XML:
<xsl:apply-templates select="anker" />
Gruß
 
Zuletzt bearbeitet von einem Moderator:
Nein, Zeilen spielen in XML keine Rolle. Es werden alle Textknoten, auch die die nur Leerzeichen enthalten, verarbeitet. Wenn du nur die Textknoten verarbeiten willst, die nicht nur aus Leerzeichen bestehen, mußt du die Knoten entsprechend filtern:
Code:
//overview/p/text()[normalize-space(.) != '']
Danke, das funktioniert sehr gut!


Wenn du dann innerhalb dieses Templates nicht nochmal explizit <xsl:apply-templates> aufrufst, werden unterhalb dieses Elements keine Templates mehr angewendet, denn sie wurden ja bereits verarbeitet...
XML:
<xsl:apply-templates select="anker" />
Gruß
Hmm, okay, ich hätte es somit so probiert:

XML:
<xsl:stylesheet version = '1.0'
     xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
	 
  <xsl:template match="overview">
  
    <xsl:apply-templates select="anker" />
  
    <xsl:for-each select="//overview/p/text()[normalize-space(.) != '']">
      <myString>
        <xsl:value-of select="." />
      </myString>
    </xsl:for-each>
  </xsl:template>
  
  <xsl:template match="anker">
    <moeglichkeit>
      <link>
        <xsl:value-of select="link/@href"/>
      </link>
      <linktext>
        <xsl:value-of select="."/>
      </linktext>
    </moeglichkeit>
  </xsl:template>

</xsl:stylesheet>

Das liefert aber wieder nur:
XML:
<?xml version="1.0" encoding="UTF-16"?>
  <myString>String 1 
	  </myString><myString>
        String 2 </myString><myString>
		String 3 </myString><myString>
      String 4
	  </myString>

Sämtliche <anker>-Elemente fehlen somit. Hmm...
(by the way: Dass der XSLT-Parser die generierte XML-Datei gleich "human-readable" einrückt, ist nicht möglich, oder?)
 
Zuletzt bearbeitet von einem Moderator:
XML:
<xsl:apply-templates select="anker" />
Sorry, die <anker> sind ja noch innerhalb von <p>.
Dann entweder
XML:
<xsl:apply-templates select="p/anker" />
oder z.B.
XML:
<xsl:apply-templates select=".//anker" />
(by the way: Dass der XSLT-Parser die generierte XML-Datei gleich "human-readable" einrückt, ist nicht möglich, oder?)
XML:
<xsl:output indent="yes" />
Gruß
 
Zuletzt bearbeitet von einem Moderator:

Neue Beiträge

Zurück