Announcement

Collapse
No announcement yet.

Selektion von Knoten an Hand direkter Vorgänger bzw. Nachfolger

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

  • Selektion von Knoten an Hand direkter Vorgänger bzw. Nachfolger

    Hallo,

    ich habe folgende Ausgangsstruktur:
    HTML Code:
    <root>
       <heading1>heading1</heading1>
       <para>para 1</para>
       <listelement first="yes">listelement 1</listelement>
       <listelement>listelement 2</listelement>
       <listelement last="yes">listelement 3</listelement>
       <para>para 2</para>
       <para>para 3</para>
       <heading2>heading2-1</heading2>
       <para>para 1-1</para>
       <para>para 1-2</para>
       <listelement_ol first="yes">listelement 1-1OL</listelement_ol>
       <listelement_ol last="yes">listelement 1-2 OL</listelement_ol>
       <para>para 1-3</para>
       <para>para 1-4</para>
       <heading2>heading2-2</heading2>
       <para>para 2-1</para>
       <listelement_ol first="yes">listelement 2-1 OL</listelement_ol>
       <listelement_ol last="yes">listelement 2-2 OL</listelement_ol>
       <para>para 2-2</para>
        <listelement first="yes">listelement 2-1</listelement>
        <listelement last="yes">listelement 2-2</listelement>
        <para>para 1-1</para>
        <para>para 1-2</para>
    </root>
    Nun soll eine Strukturierung erfolgen.
    1. Jede Datei hat nur ein Element heading1 - dass heißt die erste Strukturierung kann fix mittels LRE sect1 vorgenommen werden
    2. Anschließend wird mittels xsl:for-each-group gruppiert und zwar nach allen heading2-Elementen
    3. Weiterhin müssen alle Elemente listelement bzw. listelement_ol zu Listen gruppiert werden

    Somit ergibt sich folgender Output:
    HTML Code:
    <test>
       <sect1>
          <title>heading1</title>
          <p>para 1</p>
          <liste_ul>
             <li>listelement 1</li>
             <li>listelement 2</li>
             <li>listelement 3</li>
          </liste_ul>
          <p>para 2</p>
          <p>para 3</p>
          <sect2>
             <title2>heading2-1</title2>
             <p>para 1-1</p>
             <p>para 1-2</p>
             <liste_ol>
                <li>listelement 1-1OL</li>
                <li>listelement 1-2 OL</li>
             </liste_ol>
             <p>para 1-3</p>
             <p>para 1-4</p>
          </sect2>
          <sect2>
             <title2>heading2-2</title2>
             <p>para 2-1</p>
             <liste_ol>
                <li>listelement 2-1 OL</li>
                <li>listelement 2-2 OL</li>
             </liste_ol>
             <p>para 2-2</p>
             <liste_ul>
                <li>listelement 2-1</li>
                <li>listelement 2-2</li>
             </liste_ul>
             <p>para 1-1</p>
             <p>para 1-2</p>
          </sect2>
       </sect1>
    </test>
    Die Gruppierung in der XSL sieht folgendermaßen aus:

    HTML Code:
    <xsl:template match="/">
            <test>
                <sect1>
                    <title>
                        <xsl:value-of select="//heading1"/>
                    </title>
                    <xsl:call-template name="struktur"/>
                </sect1>
            </test>
        </xsl:template>
    
        <xsl:template name="struktur">
            <xsl:for-each-group select="//para|//heading2|//listelement|//listelement_ol"
                group-starting-with="heading2">
                <xsl:choose>
                    <xsl:when test="current()[self::heading2]">
                        <sect2>
                            <xsl:call-template name="build_liste"/>
                        </sect2>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:call-template name="build_liste"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:template>
    
        <xsl:template name="build_liste">
            <xsl:for-each-group select="current-group()" group-starting-with="listelement[@first]|listelement_ol[@first]">
                <xsl:choose>
                    <xsl:when test="current()[self::listelement|self::listelement_ol]">
                        <xsl:for-each-group select="current-group()" group-ending-with="listelement[@last]|listelement_ol[@last]">
                            <xsl:choose>
                                <xsl:when test="current()[self::listelement|self::listelement_ol]">
                                    <xsl:choose>
                                        <xsl:when  test="current()[self::listelement]">
                                            <liste_ul>
                                                <xsl:apply-templates select="current-group()"/>
                                            </liste_ul>
                                        </xsl:when>
                                        <xsl:when  test="current()[self::listelement_ol]">
                                            <liste_ol>
                                                <xsl:apply-templates select="current-group()"/>
                                            </liste_ol>
                                        </xsl:when>
                                    </xsl:choose>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:apply-templates select="current-group()"/>
                                </xsl:otherwise>
                            </xsl:choose>
                        </xsl:for-each-group>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="current-group()"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:template>
    Die Gruppierungsfunktion build_liste schmeißt in der ersten Gruppierung alle vorherigen Absatzelemente para raus, so dass für die zweite innere Gruppierung nur noch die Listenelemente und die Absätze nach der Liste übrig bleiben. Und die Absätze nach der Liste werden dann in der inneren Gruppierung rausgeschmissen, so dass nur noch die Listenelemente übrig bleiben, welche dann gruppiert werden können.

    Das ganze funktioniert soweit auch gut - da gibts nichts zu mekern. Nur würde ich gerne auf die Attribute first und last des Elements listelement in der Input-Datei verzichten und dem entsprechend die Angabe in group-starting-with bzw. group-ending-with konventionell angeben - also an Hand ihrer Position.

    Zum Beispiel ist das listelement first="yes" immer der direkte Nachfolger eines Absatzes para. Aber die Angabe

    listelement[position()=1 and preceding-sibling:ara]

    bringt mir da nicht viel

    Wie kann ich nun dieses Element identifizieren?

    Ich würde mich über Anregungen freuen.

    MFG

  • #2
    andere Weg

    Idee wie beim Compilerbau

    tag als text oder select mit concat dadurch string dazu gefügt

    Code:
    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    	<xsl:output indent="yes" method="xml"/>
    	<xsl:template match="node"/>
    	<xsl:template match="/">
    		<test>
    			<xsl:apply-templates select="root"/>
    		</test>
    	</xsl:template>
    	<xsl:template match="root">
    		<xsl:call-template name="durchlauf">
    			<xsl:with-param name="all" select="child::*"/>
    		</xsl:call-template>
    	</xsl:template>
    
    	<xsl:template name="durchlauf">
    		<xsl:param name="all"/>
    		<xsl:param name="ak" select="1"/>
    		<xsl:param name="section" select="_"/>
    		<xsl:choose>
    			<xsl:when test="starts-with(string($all[$ak]),'heading')">
    				<xsl:variable name="ename" select="concat('sect',substring(substring($all[$ak],8),1,1))"/>
    				<xsl:choose>
    					<xsl:when test="$ename=$section">
    						<xsl:value-of disable-output-escaping="yes" select="concat('&#xA;&lt;/',$ename,'&gt;')"/>
    						<xsl:value-of disable-output-escaping="yes" select="concat('&#xA;&lt;',$ename,'&gt;')"/>
    					</xsl:when>
    					<xsl:otherwise>
    						<xsl:value-of disable-output-escaping="yes" select="concat('&#xA;&lt;',$ename,'&gt;')"/>
    					</xsl:otherwise>
    				</xsl:choose>
    				<title>
    					<xsl:value-of select="$all[$ak]"/>
    				</title>
    				<xsl:call-template name="durchlauf">
    					<xsl:with-param name="ak" select="$ak + 1"/>
    					<xsl:with-param name="all" select="$all"/>
    					<xsl:with-param name="section" select="$ename"/>
    				</xsl:call-template>
    				<xsl:if test="not($ename=$section)">
    					<xsl:value-of disable-output-escaping="yes" select="concat('&#xA;&lt;','/',$ename,'&gt;')"/>
    				</xsl:if>
    			</xsl:when>
    			<xsl:when test="starts-with(string($all[$ak]),'para')">
    				<p>
    					<xsl:value-of select="$all[$ak]"/>
    				</p>
    				<xsl:call-template name="durchlauf">
    					<xsl:with-param name="ak" select="$ak + 1"/>
    					<xsl:with-param name="all" select="$all"/>
    					<xsl:with-param name="section" select="$section"/>
    				</xsl:call-template>
    			</xsl:when>
    			<xsl:when test="starts-with(string($all[$ak]),'listelement') and $all[$ak][@first='yes']">
    				<xsl:choose>
    					<xsl:when test="starts-with(substring-after($all[$ak]/name(),'_'),'ol')">
    						<xsl:text disable-output-escaping="yes">&#xA;&lt;liste_ol&gt;</xsl:text>
    					</xsl:when>
    					<xsl:otherwise>
    						<xsl:text disable-output-escaping="yes">&#xA;&lt;liste_ul&gt;</xsl:text>
    					</xsl:otherwise>
    				</xsl:choose>
    				<li>
    					<xsl:value-of select="$all[$ak]"/>
    				</li>
    				<xsl:call-template name="durchlauf">
    					<xsl:with-param name="ak" select="$ak + 1"/>
    					<xsl:with-param name="all" select="$all"/>
    					<xsl:with-param name="section" select="$section"/>
    				</xsl:call-template>
    			</xsl:when>
    			<xsl:when test="starts-with(string($all[$ak]),'listelement')and ($all[$ak][not(@last='yes')])">
    				<li>
    					<xsl:value-of select="$all[$ak]"/>
    				</li>
    				<xsl:call-template name="durchlauf">
    					<xsl:with-param name="ak" select="$ak + 1"/>
    					<xsl:with-param name="all" select="$all"/>
    					<xsl:with-param name="section" select="$section"/>
    				</xsl:call-template>
    			</xsl:when>
    			<xsl:when test="starts-with(string($all[$ak]),'listelement')and ($all[$ak][@last='yes'])">
    				<li>
    					<xsl:value-of select="$all[$ak]"/>
    				</li>
    				<xsl:choose>
    					<xsl:when test="starts-with(substring-after($all[$ak]/name(),'_'),'ol')">
    						<xsl:text disable-output-escaping="yes">&#xA;&lt;/liste_ol&gt;</xsl:text>
    					</xsl:when>
    					<xsl:otherwise>
    						<xsl:text disable-output-escaping="yes">&#xA;&lt;/liste_ul&gt;</xsl:text>
    					</xsl:otherwise>
    				</xsl:choose>
    				<xsl:call-template name="durchlauf">
    					<xsl:with-param name="ak" select="$ak + 1"/>
    					<xsl:with-param name="all" select="$all"/>
    					<xsl:with-param name="section" select="$section"/>
    				</xsl:call-template>
    			</xsl:when>
    			<xsl:otherwise>
    			</xsl:otherwise>
    		</xsl:choose>
    	</xsl:template>
    </xsl:stylesheet>

    Helmut Hagemann

    Comment

    Working...
    X