Frederik: Elemente in zwei "Ästen" des Ergebnisbaums erzeugen

Hallo!

In einem XSLT-Skript muss ich an einer Stelle Elemente in zwei "Ästen" des Ergebnisbaums erzeugen. Leider habe ich bis jetzt gar keine Ahnung, wie ich das anstellen soll.

Ich habe diese Ausgangsdatei:

<root>  
<image href="test.png" saturation="40"/>  
</root>

Diese soll in eine SVG-Datei umgewandelt werden, wobei ich für die saturation einen Filter anlegen muss:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  
  <defs>  
    <filter id="xyz">  
    ...  
    </filter>  
  </defs>  
  <image xlink:href="test.png" filter="url(#xyz)"/>  
</svg>

Dabei können eben beliebig viele image-Elemente auftreten, es soll aber nur ein defs-Element geben. Wenn ich jetzt ein template auf image anwende, kann ich das filter-Element nicht in ein bestehendes defs-Element schreiben. Oder doch?

Für Hinweise auf einen Lösungsansatz wäre ich sehr dankbar!

Liebe Grüße
Frederik

  1. Hallo Frederik,

    Dabei können eben beliebig viele image-Elemente auftreten, es soll aber nur ein defs-Element geben. Wenn ich jetzt ein template auf image anwende, kann ich das filter-Element nicht in ein bestehendes defs-Element schreiben. Oder doch?

    Ich weiß nicht, ob ich das richtig verstanden habe -- mal ein Versuch unter der Annahme dieses XML-Dokuments:

    <?xml version="1.0" encoding="ISO-8859-1"?>  
    <root>  
      <image href="test1.png" saturation="40"></image>  
      <image href="test2.png" saturation="50"></image>  
      <image href="test3.png" saturation="60"></image>  
    </root>
    

    XSL-Stylesheet:

    <?xml version="1.0" encoding="ISO-8859-1"?>  
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
      <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" media-type="image/svg+xml" indent="yes"/>  
      <xsl:template match="root">  
        <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  
          <defs>  
            <xsl:for-each select="image">  
              <filter id="xyz{position()}">  
                verarbeite saturation <xsl:value-of select="@saturation"/> ...  
              </filter>  
            </xsl:for-each>  
          </defs>  
          <xsl:for-each select="image">  
            <image xlink:href="{@href}" filter="url(#xyz{position()})"/>  
          </xsl:for-each>  
        </svg>  
      </xsl:template>  
    </xsl:stylesheet>
    

    SVG-Ergebnis:

    <?xml version="1.0" encoding="ISO-8859-1"?>  
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  
     <defs>  
      <filter id="xyz1">  
          verarbeite saturation 40 ...  
        </filter>  
      <filter id="xyz2">  
          verarbeite saturation 50 ...  
        </filter>  
      <filter id="xyz3">  
          verarbeite saturation 60 ...  
        </filter>  
     </defs>  
     <image xlink:href="test1.png" filter="url(#xyz1)"/>  
     <image xlink:href="test2.png" filter="url(#xyz2)"/>  
     <image xlink:href="test3.png" filter="url(#xyz3)"/>  
    </svg>
    

    Grüße,
    Thomas

    1. Ich weiß nicht, ob ich das richtig verstanden habe -- mal ein Versuch unter der Annahme dieses XML-Dokuments:

      <?xml version="1.0" encoding="ISO-8859-1"?>

      <root>
        <image href="test1.png" saturation="40"></image>
        <image href="test2.png" saturation="50"></image>
        <image href="test3.png" saturation="60"></image>
      </root>

        
      Genau so meinte ich es. :-)  
        
      
      > XSL-Stylesheet:  
      >   
      > ~~~xml
      
      <?xml version="1.0" encoding="ISO-8859-1"?>  
      
      > <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
      >   <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" media-type="image/svg+xml" indent="yes"/>  
      >   <xsl:template match="root">  
      >     <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  
      >       <defs>  
      >         <xsl:for-each select="image">  
      >           <filter id="xyz{position()}">  
      >             verarbeite saturation <xsl:value-of select="@saturation"/> ...  
      >           </filter>  
      >         </xsl:for-each>  
      >       </defs>  
      >       <xsl:for-each select="image">  
      >         <image xlink:href="{@href}" filter="url(#xyz{position()})"/>  
      >       </xsl:for-each>  
      >     </svg>  
      >   </xsl:template>  
      > </xsl:stylesheet>
      
      

      Ich habe die ganze Zeit an generate-id() gedacht und mich gefragt, wie ich an zwei Stellen auf die ID zurückgreifen kann. Aber natürlich ist es viel einfacher (und im Ergebnis auch leserlicher), über position() eine ID zu erzeugen.

      Jetzt können aber image-Elemente auch in geschachtelten Strukturen auftauchen, so dass ich zwar bei den defs mit xsl:for-each arbeiten kann, bei den images selbst aber ein template mit match verwenden müsste. position() gibt mir dann ja jeweils nur den Platz im aktuellen Knotenset zurück, da kann es also zu Doppelungen kommen, oder?

      Ließe sich das vielleicht mit xsl:number lösen?

      SVG-Ergebnis:

      <?xml version="1.0" encoding="ISO-8859-1"?>

      <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
      <defs>
        <filter id="xyz1">
            verarbeite saturation 40 ...
          </filter>
        <filter id="xyz2">
            verarbeite saturation 50 ...
          </filter>
        <filter id="xyz3">
            verarbeite saturation 60 ...
          </filter>
      </defs>
      <image xlink:href="test1.png" filter="url(#xyz1)"/>
      <image xlink:href="test2.png" filter="url(#xyz2)"/>
      <image xlink:href="test3.png" filter="url(#xyz3)"/>
      </svg>

        
      So soll es prinzipiell aussehen, aber es sind eben auch geschachtelte Strukturen möglich.  
        
      Danke aber schon mal für den Hinweis, ich denke, das geht in die richtige Richtung. Damit werde ich sicherlich irgendwie zum Ziel kommen.  
        
      Liebe Grüße  
      Frederik
      
      1. Hallo,

        Was verstehst du unter geschachtelten Strukturen, Beispiel xml?

        1. Was verstehst du unter geschachtelten Strukturen, Beispiel xml?

          <?xml version="1.0" encoding="ISO-8859-1"?>  
          <root>  
            <image href="test1.png" saturation="40"></image>  
            <div>  
              <image href="test2.png" saturation="50"></image>  
              <image href="test3.png" saturation="60"></image>  
            </div>  
          </root>
          

          Wenn ich es richtig sehe, haben ja jetzt sowohl das erste als auch das zweite image eine position() von 1, weil sie jeweils das erste Element in ihrem Zweig sind, oder?

          Diese Struktur muss auch im Ergebnisdokument rauskommen, also z.B.

          <?xml version="1.0" encoding="ISO-8859-1"?>  
          <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">  
           <defs>  
            <filter id="xyz1">  
                verarbeite saturation 40 ...  
              </filter>  
            <filter id="xyz2">  
                verarbeite saturation 50 ...  
              </filter>  
            <filter id="xyz3">  
                verarbeite saturation 60 ...  
              </filter>  
           </defs>  
           <image xlink:href="test1.png" filter="url(#xyz1)"/>  
           <svg>  
            <image xlink:href="test2.png" filter="url(#xyz2)"/>  
            <image xlink:href="test3.png" filter="url(#xyz3)"/>  
           </svg>  
          </svg>
          

          Liebe Grüße
          Frederik

          1. Hallo Frederik,

            <?xml version="1.0" encoding="ISO-8859-1"?>

            <root>
              <image href="test1.png" saturation="40"></image>
              <div>
                <image href="test2.png" saturation="50"></image>
                <image href="test3.png" saturation="60"></image>
              </div>
            </root>

            
            >   
            > Wenn ich es richtig sehe, haben ja jetzt sowohl das erste als auch das zweite image eine position() von 1, weil sie jeweils das erste Element in ihrem Zweig sind, oder?  
              
            Ein `select="//image"`{:.language-xml} würde weiterhin wie von mir beschrieben funktionieren.  
              
            Grüße,  
            Thomas