xml->xsl->html

... wie könnte ich die Position des letzten Tags vor text() ermitteln, wenn ich kein bestimmtes Tag hätte, das immer da steht? oder die Position vom Text selbst vielleicht? Habe schon viel gesucht, konnte aber keine vernünftige Antwort finden.
Hallo,
du müsstest erst mal ein Template für die Elementknoten machen, sonst greift die Default-Regel. Anschließend kannst du die Position des Textknotens im "para"-Element bestimmen. Zum Beispiel so:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

<xsl:template match="node()" />

<xsl:template match="text()">
    <xsl:variable name="pos" select="position()" />
    <xsl:copy-of select="../node()[$pos - 1]" />
</xsl:template>

</xsl:stylesheet>
 
Hallo allerseits!

ich bin's wieder, mit meinem blöden Problem... Das ganze ist etwas komplozierter geworden. Das zu trennende Element in neueren "XML-Ausgaben" hat nun Text an mehreren Stellen und kann auch so aussehen:
Code:
<para>Text1 <bold>text</bold><trenntag/><italic>test</italic>Text2 <sub>text3</sub> text4</para>
oder so:
Code:
<para>Text1<trenntag/><italic>test</italic><italic>text3</italic> text4</para>
oder auch so:
Code:
<para><bold>text</bold><trenntag/><italic>test</italic>Text2 <sub>text3</sub> text4</para>
und es können wohl auch andere Variationen kommen, leider habe ich keinen Einfluß darauf.

Alles, was vor dem <trenntag/> sich befindet, muß ins <div1>, der Rest - ins <div2>

Hab schon vieles ausprobiert, leider ohne Erfolg. Anbei eine Variante, die ich heute ausprobiert habe:

Code:
<xsl:template match="//para/trenntag">
<!-- Position des Trennelements ermittelt -->
  <xsl:variable name="pos" select="position()" />
 <!-- Alle Elemente vor dem Trenntag ausgeben lassen -->
  <xsl:for-each select="preceding-sibling::*">
    <xsl:for-each select="descendant::*"> 
        <xsl:apply-templates select="."/>
    </xsl:for-each>  
  </xsl:for-each>
 <!-- Alle Elemente nach dem Trenntag ausgeben lassen -->
  <xsl:for-each select="following-sibling::*">
        <xsl:for-each select="descendant::*">  
            <xsl:apply-templates select="."/>
        </xsl:for-each>  
  </xsl:for-each>
</xsl:template>

Es kommt leider nichts vernünftiges dabei raus.

Noch ein verzweifelter Versuch:

Code:
<xsl:template match="//para">
<!-- Position des Trenntags ermitteln -->
  <xsl:variable name="pos" select="(count(*[name()='trenntag']/preceding-sibling::*[last()]) + 1)"/>
  <xsl:variable name="pos2" select="$pos+1"/>
 

   <xsl:choose>
<!-- Variante, wo vor dem Trenntag nur Text steht -->
   <xsl:when test="$pos=1">
     <div class="div1">
       <xsl:value-of select="node()"/>
     </div>
     <div class="div2">
      <xsl:apply-templates select="text()[$pos+1]|*[(position()&gt;$pos)]"/>
     </div>
   </xsl:when>
   <xsl:otherwise>
<!-- Variante, wo mehrere Tags  vor dem Trenntag stehen -->

 <div class="div1">
    	<xsl:apply-templates select="node()[position()&lt;$pos]|*[(position()&lt;$pos2)]"/>
 </div>
 <div class="div2">
 	<xsl:apply-templates select="text()[$pos]|node()[position()&gt;$pos]|*[(position()&gt;$pos)]"/>
 	
 </div>
 
 
 </xsl:otherwise>
 </xsl:choose>
 </div>
</xsl:template>

Diese Variante macht's zwar etwas besser, aber trotzdem nicht richtig.

Was mache ich falsch?
Help!!

Danke im voraus
 
Zuletzt bearbeitet:
Hi!

Also das geht viel einfacher (XSLT 1.0):
XML:
<xsl:template match="//para">
 <xsl:variable name="position" select="position(./trenntag)"/>
 <div id="div1">
  <xsl:for-each select="./*[position() &lt; $position]">
   <xsl:apply-temlates/>
  </xsl:for-each>
 </div>
 <div id="div2">
  <xsl:for-each select="./*[position() &gt; $position]">
   <xsl:apply-temlates/>
  </xsl:for-each>
 </div>
</xsl:template>

Nicht getestet, sollte aber klappen.

Gruß
Enum
 
Hi!

danke, aber das hier: "position(./trenntag)" funktioniert nicht, habe auch vorhin ausprobiert. Die Fehlermeldung lautet: "Eine XPath-Funktion wurde mit einer falschen Anzahl an Argumenten aufgerufen."
 
Sorry, etwas müde... :p
XML:
<xsl:template match="//para">
 <xsl:for-each select="./*">
  <xsl:if test="local-name() = 'trenntag'">
   <xsl:call-template name="trenntag"/>
  </xsl:if>
 </xsl:for-each>
</xsl:template>

<xsl:template name="trenntag">
 <xsl:variable name="position" select="position()"/>
 <div id="div1">
  <xsl:for-each select="../*[position() &lt; $position]">
   <xsl:apply-templates select="."/>
  </xsl:for-each>
 </div>
 <div id="div2">
  <xsl:for-each select="../*[position() &gt; $position]">
   <xsl:apply-templates select="."/>
  </xsl:for-each>
 </div>
</xsl:template>

Gruß
Enum
 
Hi!

Danke!

habe gerade getestet. Leider das, was dabei rauskommt, nicht viel besser als das, was ich vorhin bekommen hattte. <div1>-Inhalt wird fast richtig ausgegeben (nur im Fall, wenn Text vor dem Trenntag steht, kommt nix), div2 bleibt leer :confused:
Any Idea?
 
Hi!

Damit "reine" Textknoten berücksichtigt werden, musst Du anstelle des Asterisk (*) child::node() in den Selektor einbauen.
Hab gerade folgendes Stylesheet getestet und es funktioniert einwandfrei:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml"/>

  <xsl:template match="//para">
   <xsl:for-each select="./*">
    <xsl:if test="local-name() = 'trenntag'">
     <xsl:call-template name="trenntag"/>
    </xsl:if>
   </xsl:for-each>
  </xsl:template>

  <xsl:template name="trenntag">
   <xsl:variable name="position" select="position()"/>
   <div id="div1">
    <xsl:for-each select="../child::node()[position() &lt; $position]">
     <xsl:apply-templates select="."/>
    </xsl:for-each>
   </div>
   <div id="div2">
    <xsl:for-each select="../child::node()[position() &gt; $position]">
     <xsl:apply-templates select="."/>
    </xsl:for-each>
   </div>
  </xsl:template>

  <xsl:template match="node()|@*">
   <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
   </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Gruß
Enum
 
Danke! Fast perfekt! :)

Eine Frage noch:

in diesem Fall:

Code:
<para>text<trenntag/><tag1>der rest</tag1>text</para>
ist der Wert der Variable $position gleich 1. Also, wird der Text vor dem Trennzeichen nicht ausgegeben (es wird wohl ab 1 gezählt, nicht ab 0, oder?). Wie kann ich den Template überreden auch etwas, das vor position 1 steht, ausgeben lassen?

Danke noch mal für Deine Hilfe!
 
Hi!

Hol' einfach das nach was ich vergessen habe; pass' Zeile 8 vom Beispiel so an wie mit den Zeilen 18 und 23 schon geschehen.

Gruß
Enum
 
hm... ich habe es so ausprobiert:

<xsl:for-each select="../child::node()[position() &lt; $position]|../child::node()[$position]">

und da kam auch schon das raus, was ich brauche. Aber danke, ich probier's gleich auch mit der Zeile 8!


Nachtrag: Danke, es hat funktioniert!
:)
 

Neue Beiträge

Zurück