Frank Spangenberg: Variable und String mit "xsl:if" vergleichen

Hallo,

folgende Struktur:

...
<xsl:variable name="switch"></xsl:variable>
...

<xsl:for-each select="...">

xsl:choose

<xsl:when test="...">

...

</xsl:when>

<xsl:when test="...">

<xsl:if test="$switch = 'on'">

...

</xsl:if>

<xsl:if test="$switch = ''">

<xsl:variable name="switch">on</xsl:variable>

</xsl:if>

</xsl:when>

xsl:otherwise
  ...
  </xsl:otherwise>

</xsl:choose>

</xsl:for-each>

Beim ersten Durchlauf hat $switch keinen Wert und bekommt
im 2. "xsl:when" durch das 2. "xsl:if" den Wert "on".

Beim nächsten "xsl:for-each" wird aber "<xsl:if test="$switch = 'on'">"
übergangen und statt dessen "<xsl:if test="$switch = ''">"
ausgeführt.

Wo könnte der Fehler liegen?

Danke!

--
Mit freundlichem Gruß
Frank Spangenberg
  1. Hallo,

    Wo könnte der Fehler liegen?

    Würde mich wundern, wenn das überhaupt geht:
    meines Wissens nach darfst du eine Variable in XSL nicht 2 x namentlich erwähnen.
    Dafür musst du with-param nehmen und dein template rekursiv durchlaufen.

    bydey

    --
    -- noch immer ein erfolgloser <DIV> Jünger --
  2. Hallo,

    folgende Struktur:
    <xsl:variable name="switch"></xsl:variable>
      <xsl:when test="...">
       <xsl:if test="$switch = 'on'">

    Wird in diesem Fall nie zutreffen.

    Beim ersten Durchlauf hat $switch keinen Wert und bekommt
    im 2. "xsl:when" durch das 2. "xsl:if" den Wert "on".

    Nein, bekommt sie nicht. Wie schon gesagt, Variablen kannst du in XSLT nicht neue Werte zuweisen.

    Die Lösung hast du auch schon genannt bekommen, du must dein Template umbauen und statt der Variable einen Parameter verwenden. Dessen Wert kannst du bei einem rekursiven Aufruf des Templates neu setezen.

    Grüße
    Thomas

    1. Ok, vielen Dank.

      Ich habe das ganze jetzt umgebaut, ohne Parameter/Variablen...

      Die XML-Datei sieht ungefähr so aus:

      ...
      <text:p text:style-name="h1">bla</text:p>
      <text:p text:style-name="p">bla</text:p>
      <text:p text:style-name="p">bla</text:p>
      <text:p text:style-name="h1">bla</text:p>
      <text:p text:style-name="h2">bla</text:p>
      <text:p text:style-name="h3">bla</text:p>
      <text:p text:style-name="p">bla</text:p>
      <text:p text:style-name="p">bla</text:p>
      <text:p text:style-name="p">bla</text:p>
      <text:p text:style-name="h2">bla</text:p>
      <text:p text:style-name="h3">bla</text:p>
      <text:p text:style-name="p">bla</text:p>
      <text:p text:style-name="p">bla</text:p>
      <text:p text:style-name="p">bla</text:p>
      <text:p text:style-name="h2">bla</text:p>
      <text:p text:style-name="h3">bla</text:p>
      ...

      Die Attribute werden zu Tags, also 'style-name="h1"'
      zu <h1>bla</h1>.

      Nun möchte ich in der Ziel-XML-Datei vor jedem 'style-name="h2"'
      (also <h2>bla</h2>) das letzte vorangegangene ‘style-name="h1"‘
      (also <h1>bla</h1>) einfügen, so dass folgendes entsteht:

      <h1>bla_h1-1</h1> *Überschrift 1-1*
      <p>bla_p-1</p>
      ...
      <h1>bla_h1-2</h1> *Überschrift 1-2*
      <h2>bla_h2-1</h2>
      <h3>bla_h3-1</h3>
      ...
      <h1>bla_h1-2</h1> *Überschrift 1-2*
      <h2>bla_h2-2</h2>
      <h3>bla_h3-2</h3>

      Durch xsl:if bei einem 'style-name="h2"' rufe ich also
      den Wert des letzten vorangegangenen ‘style-name="h1"‘ auf:

      preceding-sibling::text:p[position()=1][@text:style-name = 'h1']

      Leider funktioniert das nicht...

      --
      Mit freundlichem Gruß
      Frank Spangenberg
      1. Hallo,

        Durch xsl:if bei einem 'style-name="h2"' rufe ich also
        den Wert des letzten vorangegangenen ‘style-name="h1"‘ auf:

        preceding-sibling::text:p[position()=1][@text:style-name = 'h1']

        Ohne mehr von deinem XSL zu sehen, kann ich leider nichts dazu sagen.

        Grüße
        Thomas

        1. <xsl:for-each select="//text:h | //text:p">

          xsl:choose
            <xsl:when test="@text:style-name='h2'">

          <xsl:if test="preceding-sibling::node()[2]/@text:style-name != 'h1'">

          <h1>
              <xsl:value-of select="preceding-sibling::text:p[@text:style-name = 'h1']"/>
              </h1>

          ...

          1. Sorry, war falsch, hier richtig:

            <xsl:for-each select="//text:h | //text:p">

            xsl:choose
              <xsl:when test="@text:style-name='h2'">

            <xsl:if test="preceding-sibling::node()[2]/@text:style-name != 'h1'">

            <h1>
                <xsl:value-of select="preceding-sibling::text:p[position()=1][@text:style-name = 'h1']"/>
                </h1>
            ...

            --
            Mit freundlichem Gruß
            Frank Spangenberg
            1. Hallo,

              --------------- xml ----------------------

              <?xml version="1.0" encoding="iso-8859-1"?>
              <data xmlns:text="http://example.org/text">
               <text:p text:style-name="h1">h1 1</text:p>
               <text:p text:style-name="p">p 1</text:p>
               <text:p text:style-name="p">p 2</text:p>
               <text:p text:style-name="h1">h1 2</text:p>
               <text:p text:style-name="h2">h2 1</text:p>
               <text:p text:style-name="h3">h3 1</text:p>
               <text:p text:style-name="p">p 3</text:p>
               <text:p text:style-name="p">p 4</text:p>
               <text:p text:style-name="p">p 5</text:p>
               <text:p text:style-name="h2">h2 2</text:p>
               <text:p text:style-name="h3">h3 2</text:p>
               <text:p text:style-name="p">p 6</text:p>
               <text:p text:style-name="p">p 7</text:p>
               <text:p text:style-name="p">p 8</text:p>
               <text:p text:style-name="h2">h2 3</text:p>
               <text:p text:style-name="h3">h3 3</text:p>
               <text:p text:style-name="p">p 9</text:p>
               <text:p text:style-name="p">p 10</text:p>
               <text:p text:style-name="h1">h1 3</text:p>
               <text:p text:style-name="h2">h2 4</text:p>
               <text:p text:style-name="h3">h3 4</text:p>
               <text:p text:style-name="p">p 11</text:p>
               <text:p text:style-name="p">p 12</text:p>
               <text:p text:style-name="p">p 13</text:p>
              </data>

              --------------------- xsl ----------------
              <?xml version="1.0" encoding="iso-8859-1"?>
              <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:text="http://example.org/text">
               <xsl:template match="/data">
                <html>
                 <head><title>Untitled</title></head>
                 <body>
                  <xsl:for-each select="//text:h | //text:p">
                   xsl:choose
                    <xsl:when test="@text:style-name='h1'">
                     <xsl:if test="following-sibling::node()[1]/@text:style-name != 'h2'">
                      <h1>
                       <xsl:value-of select="."/>
                      </h1>
                     </xsl:if>
                    </xsl:when>
                    <xsl:when test="@text:style-name='h2'">
                     <xsl:if test="preceding-sibling::node()[2]/@text:style-name != 'h1'">
                      <h1>
                       <xsl:value-of select="preceding-sibling::text:p[@text:style-name = 'h1'][1]"/>
                      </h1>
                     </xsl:if>
                     <h2>
                      <xsl:value-of select="."/>
                     </h2>
                    </xsl:when>
                    <xsl:when test="@text:style-name='h3'">
                     <h3>
                      <xsl:value-of select="."/>
                     </h3>
                    </xsl:when>
                    <xsl:when test="@text:style-name='p'">
                     <p>
                      <xsl:value-of select="." />
                     </p>
                    </xsl:when>
                   </xsl:choose>
                  </xsl:for-each>
                 </body>
                </html>
               </xsl:template>
              </xsl:stylesheet>

              ------------------------- ausgabe --------------
              <html xmlns:text="http://example.org/text">
              <head>
              <META http-equiv="Content-Type" content="text/html; charset=UTF-16">
              <title>Untitled</title></head>
              <body>
              <h1>h1 1</h1>
              <p>p 1</p>
              <p>p 2</p>
              <h1>h1 2</h1>
              <h2>h2 1</h2>
              <h3>h3 1</h3>
              <p>p 3</p>
              <p>p 4</p>
              <p>p 5</p>
              <h1>h1 2</h1>
              <h2>h2 2</h2>
              <h3>h3 2</h3>
              <p>p 6</p>
              <p>p 7</p>
              <p>p 8</p>
              <h1>h1 2</h1>
              <h2>h2 3</h2>
              <h3>h3 3</h3>
              <p>p 9</p>
              <p>p 10</p>
              <h1>h1 3</h1>
              <h2>h2 4</h2>
              <h3>h3 4</h3>
              <p>p 11</p>
              <p>p 12</p>
              <p>p 13</p>
              </body>
              </html>

              Grüße
              Thomas

              1. Hallo Thomas,

                vielen Danke für die Mühe!

                Hier die endgültige Version:

                <?xml version="1.0" encoding="UTF-8"?>
                <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" exclude-result-prefixes="text">
                <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no"/>
                  <xsl:template match="/">
                   <root>
                   <document>
                     <xsl:for-each select="//text:h | //text:p">
                      xsl:choose
                       <xsl:when test="@text:style-name='h1'">
                       <h1>
                        <xsl:value-of select="."/>
                       </h1>
                      </xsl:when>
                      <xsl:when test="@text:style-name='h2'">
                          <xsl:if test="preceding-sibling::node()[1]/@text:style-name != 'h1'">
                        <h1>
                         <xsl:value-of select="preceding-sibling::node()[@text:style-name = 'h1'][1]"/>
                        </h1>
                       </xsl:if>
                       <h2>
                        <xsl:value-of select="."/>
                         </h2>
                      </xsl:when>
                      <xsl:when test="@text:style-name='h3'">
                         <h3>
                       <xsl:value-of select="."/>
                         </h3>
                      </xsl:when>
                      <xsl:when test="@text:style-name='p'">
                         <p>
                       <xsl:value-of select="." />
                         </p>
                      </xsl:when>
                      </xsl:choose>
                    </xsl:for-each>
                   </document>
                  </root>
                  </xsl:template>
                </xsl:stylesheet>

                --
                Mit freundlichem Gruß
                Frank Spangenberg