dey: / XSL: Knoten in Variable + neues Feld

Hallo,

einen Knoten in eine Variable zu speichern habe ich schon gemacht.
Ich würde jetzt gerne ein zusätzliches Feld mit in diese Variable speichern, um den Inhalt der Variable für die Ausgabe nach diesem neuen Feld zu sortieren.
(Wie) geht das?

bydey

--
-- bydey ist die Signatur und Verabschiedung, nicht der Nick --
-- Navigate all your PHP web projects with  PHP Project Browser--
  1. Hallo,

    einen Knoten in eine Variable zu speichern habe ich schon gemacht.
    Ich würde jetzt gerne ein zusätzliches Feld mit in diese Variable speichern, um den Inhalt der Variable für die Ausgabe nach diesem neuen Feld zu sortieren.
    (Wie) geht das?

    Wie sieht Deine bisherige Struktur aus und was willst Du genau machen?

    Prinzipiell funktioniert natürlich sowas:

    <xsl:variable name="items">  
      <xsl:for-each select="...">  
        <item>  
          <!-- Alte Attribute kopieren -->  
          <xsl:copy-of select="@*" />  
          <!-- Alte Kindknoten kopieren -->  
          <xsl:copy-of select="node()" />  
          <!-- Weitere Kindknoten -->  
          <sonstwas>  
            <xsl:value-of select="..." />  
          </sonstwas>  
        </item>  
      </xsl:for-each>  
    </xsl:variable>
    

    Allerdings kannst Du die Variable in XSLT 1.0 nicht mehr in xsl:for-each packen, das gibt einen Fehler - in XSLT 2.0 geht das. Wenn Du also die Sortierung ändern willst, musst Du das bereits beim Anlegen der Variable machen - Du kannst mit XSLT 1.0 den Inhalt der Variable lediglich per <xsl:copy-of select="$variable" /> an einer bestimmten Stelle ins Dokument einfügen, nicht mehr.

    Viele Grüße,
    Christian

    1. Hallo Christian,

      Wie sieht Deine bisherige Struktur aus und was willst Du genau machen?

      <xsl:variable name="root" select="/" />
      Das ist natürlich bis hierhin sehr simple, da ich den kompletten Knoten ungefiltert weiter gebe.

      Prinzipiell funktioniert natürlich sowas:

      <xsl:variable name="items">

      <xsl:for-each select="...">
          <item>
            <!-- Alte Attribute kopieren -->
            <xsl:copy-of select="@*" />
            <!-- Alte Kindknoten kopieren -->
            <xsl:copy-of select="node()" />
            <!-- Weitere Kindknoten -->
            <sonstwas>
              <xsl:value-of select="..." />
            </sonstwas>
          </item>
        </xsl:for-each>
      </xsl:variable>

      
      >   
      > Allerdings kannst Du die Variable in XSLT 1.0 nicht mehr in <xsl:for-each> packen, das gibt einen Fehler - in XSLT 2.0 geht das. Wenn Du also die Sortierung ändern willst, musst Du das bereits beim Anlegen der Variable machen - Du kannst mit XSLT 1.0 den Inhalt der Variable lediglich per <xsl:copy-of select="$variable" /> an einer bestimmten Stelle ins Dokument einfügen, nicht mehr.  
        
      Wenn ich nicht nach dem zusätzlichen Feld sortieren kann nützt es mir nix. Nur aus diesem Grund dachte ich überhaupt an eine Variable: zwischenspeichern -> zusätzliches Feld -> nach diesem sortieren/ gruppieren -> Ausgabe  
        
      Wenn das so nicht geht kann man es wieder vergessen.  
        
      bydey
      
      -- 
      \-- bydey ist die Signatur und Verabschiedung, nicht der Nick --  
        
      \-- Navigate all your PHP web projects with  [PHP Project Browser](http://deynews.de/ppb/)--
      
      1. Hallo!

        Allerdings kannst Du die Variable in XSLT 1.0 nicht mehr in xsl:for-each packen, das gibt einen Fehler - in XSLT 2.0 geht das. Wenn Du also die Sortierung ändern willst, musst Du das bereits beim Anlegen der Variable machen - Du kannst mit XSLT 1.0 den Inhalt der Variable lediglich per <xsl:copy-of select="$variable" /> an einer bestimmten Stelle ins Dokument einfügen, nicht mehr.

        Wenn ich nicht nach dem zusätzlichen Feld sortieren kann nützt es mir nix. Nur aus diesem Grund dachte ich überhaupt an eine Variable: zwischenspeichern -> zusätzliches Feld -> nach diesem sortieren/ gruppieren -> Ausgabe

        Wo kommt eigentlich die Information "zusätzliches Feld" her? Die musst Du ja auch irgendwie dynamisch bekommen, oder?

        Denn bei <xsl:sort /> kannst Du beim select-Attribut nämlich einen beliebigen XPath-Ausdruck angeben, d.h. sowas funktioniert durchaus:

        <xsl:for-each select="...">  
          <xsl:sort select="translate (elem/@attrib, 'ABC', 'DEF')" />  
          ...  
        </xsl:for-each>
        

        (Jetzt mal beispielhaft)

        Funktioniert in XSLT 1.0 natürlich nur, wenn Du die Information bezüglich des zusätzlichen Feldes auch in einem geschlossenen XPath-Ausdruck unterbringen kannst und keine Bedingungen / Templates benötigst. Da ist XSLT 2.0 auch wieder besser, weil man sich da eigene XPath-Funktionen definieren kann und außerdem stehen in XPath 2.0 auch if/then/else und for u.ä. zur Verfügung.

        Als weitere Alternative bestünde natürlich die Möglichkeit, das Dokument zweimal durch XSLT zu jagen: Das erste Mal werden nur Zusatzinformationen hinzugefügt, das zweite Mal erfolgt die Anzeigelogik.

        Viele Grüße,
        Christian

        1. Hallo,

          Wo kommt eigentlich die Information "zusätzliches Feld" her? Die musst Du ja auch irgendwie dynamisch bekommen, oder?

          Denn bei <xsl:sort /> kannst Du beim select-Attribut nämlich einen beliebigen XPath-Ausdruck angeben, d.h. sowas funktioniert durchaus:

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

          <xsl:sort select="translate (elem/@attrib, 'ABC', 'DEF')" />
            ...
          </xsl:for-each>

          
          >   
          > (Jetzt mal beispielhaft)  
          >   
          > Funktioniert in XSLT 1.0 natürlich nur, wenn Du die Information bezüglich des zusätzlichen Feldes auch in einem geschlossenen XPath-Ausdruck unterbringen kannst und keine Bedingungen / Templates benötigst. Da ist XSLT 2.0 auch wieder besser, weil man sich da eigene XPath-Funktionen definieren kann und außerdem stehen in XPath 2.0 auch if/then/else und for u.ä. zur Verfügung.  
            
          Das sieht als Ansatz gut aus. Die Sortierung soll nach Häufigkeit sein:  
          ~~~xml
            
          <xsl:sort select="count(//FeederReportUnit/Unit[fsPartNum = $tmp_fsPartNum])" />  
          
          

          Würde das so funktionieren?
          Auch wenn ich vorher Gruppiere?

            
          <xsl:for-each select="FeederReportUnit/Unit[count(. | key('partnumbers', fsPartNum)[1]) = 1 and fsPartNum!='']">  
          
          

          Als weitere Alternative bestünde natürlich die Möglichkeit, das Dokument zweimal durch XSLT zu jagen: Das erste Mal werden nur Zusatzinformationen hinzugefügt, das zweite Mal erfolgt die Anzeigelogik.

          Das war ja mein Ansatz, aber wie/ wo lege ich das Zwischenergebnis ab?

          bydey

          --
          -- bydey ist die Signatur und Verabschiedung, nicht der Nick --
          -- Navigate all your PHP web projects with  PHP Project Browser--
          1. Hallo!

            Das sieht als Ansatz gut aus. Die Sortierung soll nach Häufigkeit sein:

            <xsl:sort select="count(//FeederReportUnit/Unit[fsPartNum = $tmp_fsPartNum])" />

            
            > Würde das so funktionieren?  
            > Auch wenn ich vorher Gruppiere?  
            > ~~~xml
              
            
            > <xsl:for-each select="FeederReportUnit/Unit[count(. | key('partnumbers', fsPartNum)[1]) = 1 and fsPartNum!='']">  
            > 
            
            

            Es wäre nett, wenn Du mal etwas Beispieldaten und etwas mehr Beispielcode lieferst. Und eventuell auch einen Hinweis, welche Ausgabe Du erreichen willst, auch ganz brauchbar. Wenn Du einfach nur mit XPath um Dich wirfst, dann ist es etwas schwer, da durchzusteigen...

            Als weitere Alternative bestünde natürlich die Möglichkeit, das Dokument zweimal durch XSLT zu jagen: Das erste Mal werden nur Zusatzinformationen hinzugefügt, das zweite Mal erfolgt die Anzeigelogik.
            Das war ja mein Ansatz, aber wie/ wo lege ich das Zwischenergebnis ab?

            Wie verarbeitest Du Dein XSLT bisher?

            Viele Grüße,
            Christian

            1. Hallo,

                
                 <xsl:template name="create_split_table">  
                 <h2 class="pagebreak">Report fuer mehrfach geruestete Bauteile</h2>  
                 <table class="split" border="1" bordercolor="black" cellpadding="2"  cellspacing="0" >  
                             <thead>  
                                <tr>  
                
                                   <th class="partnumber">Partnumbers:</th>  
                
                                   <th class="sum">Anzahl Rollen:</th>  
                
                                   <th class="sumgroup">Summe</th>  
                
                                </tr>  
                             </thead>  
                
                             <tbody>  
                     <!-- //FME// group part numbers // -->  
                  <xsl:for-each select="FeederReportUnit/Unit[count(. | key('partnumbers', fsPartNum)[1]) = 1 and fsPartNum!='']">  
                                  <xsl:variable name="tmp_fsPartNum">  
                    <xsl:value-of select="fsPartNum"/>  
                   </xsl:variable>  
                   <!-- //FME// find splitted part numbers // -->  
                   <xsl:variable name="qtyreels">  
                    <xsl:value-of select="count(//FeederReportUnit/Unit[fsPartNum = $tmp_fsPartNum])" />  
                   </xsl:variable>  
                   <xsl:if test="$qtyreels >1">  
                   <tr>  
                   <td>  
                   <xsl:choose>  
                     <!-- //FME// set xxx format // -->  
                     <xsl:when test="translate(format-number(fsPartNum,'000,000,000'),',',' ')='NaN'">  
                     <xsl:value-of select="fsPartNum"/>  
                     </xsl:when>  
                     <xsl:otherwise>  
                      <font class="pnum"><xsl:value-of select="translate(format-number(fsPartNum,'000,000,000'),',',' ')"/></font>  
                     </xsl:otherwise>  
                   </xsl:choose>  
                   </td>  
                   <td><xsl:value-of select="$qtyreels"/></td>  
                   <!-- //FME// qty for all slots in case of split // -->  
                   <td><xsl:value-of select="sum(//FeederReportUnit/Unit[fsPartNum = $tmp_fsPartNum]/fsPartQty)" /></td></tr>  
                   </xsl:if>  
                              </xsl:for-each>  
                             </tbody>  
                          </table>  
                 </xsl:template>  
              
              

              Mach ich doch gerne. Das ist der Stand jetzt. Dank meiner Inkompetenz konnte ich den Kunden davon überzeugen, die Sortierung nach Häufigkeit der Rollen fallen zu lassen. Dieses Ergebnis stellt ihn zufrieden

              Wie verarbeitest Du Dein XSLT bisher?

              Ich gebe direct im IE aus:

              • js ruft innerhalb von html XML mit XSL als Object auf
              • XML wird dann mit XSL geparst und die notwendigen HTML-Elemente hinzugefügt.

              bydey

              --
              -- bydey ist die Signatur und Verabschiedung, nicht der Nick --
              -- Navigate all your PHP web projects with  PHP Project Browser--
              1. Hi,

                [code]

                Der ist leider unvollständig. ;-)

                Ich habe nämlich immer noch keine Ahnung, wie Deine Ausgangsdaten (beispielhaft) aussehen. Außerdem ist mir immer noch nicht ganz klar: Sehe ich das richtig, dass Du nach der zweiten generierten Spalte sortieren willst?

                Deine <xsl:key />-Definition für den Key 'partnumbers' wäre außerdem noch interessant.

                Wie verarbeitest Du Dein XSLT bisher?
                Ich gebe direct im IE aus:

                • js ruft innerhalb von html XML mit XSL als Object auf
                • XML wird dann mit XSL geparst und die notwendigen HTML-Elemente hinzugefügt.

                Naja, ich weiß ja nicht, wie genau Du den MSXML-Prozessor aufrufst, aber Du erhälst doch vom XSLT-Prozessor eine Zeichenkette, die das Ergebnis der Transformation darstellt. Anstelle dass Du die direkt ins Dokument einbaust, kannst Du die ja nochmal durch ein anderes Stylesheet jagen und das Ergebnis erst ins Dokument einbauen. Auch hier: Ohne den bisherigen Code zu kennen, kann man Dir nicht wirklich helfen.

                Viele Grüße,
                Christian

                1. Hallo,

                  XML:

                    
                  <?xml version="1.0" encoding="UTF-8"?>  
                  <?xml-stylesheet type='text/xsl' href='FeederReportUnit.xsl'?>  
                  <FeederReportUnit>  
                  <Unit>  
                  <fsSetPos>fsSetPos</fsSetPos><fsPartNum>fsPartNum</fsPartNum><fsFdrName>fsFdrName</fsFdrName><pkgInfoPkgType>pkgInfoPkgType</pkgInfoPkgType><pkgInfoTapeWidth>pkgInfoTapeWidth</pkgInfoTapeWidth><pkgInfoFeedPitch>pkgInfoFeedPitch</pkgInfoFeedPitch><favFdrPkg>favFdrPkg</favFdrPkg><favReelWidth>favReelWidth</favReelWidth><asBodyHeight>asBodyHeight</asBodyHeight><fsStatus>fsStatus</fsStatus><fsPartQty>fsPartQty</fsPartQty><fsTrayDir>fsTrayDir</fsTrayDir><pnPartComment>pnPartComment</pnPartComment><pnBarcode>pnBarcode</pnBarcode></Unit>  
                  <Unit>  
                  <fsSetPos>1-  2</fsSetPos><fsPartNum>674200004</fsPartNum><fsFdrName>KT-0800-330</fsFdrName><pkgInfoPkgType>Emboss</pkgInfoPkgType><pkgInfoTapeWidth>8mm</pkgInfoTapeWidth><pkgInfoFeedPitch>4</pkgInfoFeedPitch><favFdrPkg>Paper/Emboss</favFdrPkg><favReelWidth>8</favReelWidth><asBodyHeight>0.55</asBodyHeight><fsStatus>Fixed</fsStatus><fsPartQty>0</fsPartQty><fsTrayDir>0</fsTrayDir><pnPartComment></pnPartComment><pnBarcode></pnBarcode></Unit>
                  

                  Ich habe nämlich immer noch keine Ahnung, wie Deine Ausgangsdaten (beispielhaft) aussehen. Außerdem ist mir immer noch nicht ganz klar: Sehe ich das richtig, dass Du nach der zweiten generierten Spalte sortieren willst?

                  Ja

                  Deine <xsl:key />-Definition für den Key 'partnumbers' wäre außerdem noch interessant.

                    
                  <xsl:key name="partnumbers" match="FeederReportUnit/Unit" use="fsPartNum" />
                  

                  Wie verarbeitest Du Dein XSLT bisher?
                  Ich gebe direct im IE aus:

                  • js ruft innerhalb von html XML mit XSL als Object auf
                  • XML wird dann mit XSL geparst und die notwendigen HTML-Elemente hinzugefügt.

                  Naja, ich weiß ja nicht, wie genau Du den MSXML-Prozessor aufrufst,

                    
                  <?xml version="1.0"  encoding="iso8859-1"?>  
                  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
                          xmlns:fo="http://www.w3.org/1999/XSL/Format" version='1.0'>
                  

                  war es das was du meinst?

                  aber Du erhälst doch vom XSLT-Prozessor eine Zeichenkette, die das Ergebnis der Transformation darstellt. Anstelle dass Du die direkt ins Dokument einbaust, kannst Du die ja nochmal durch ein anderes Stylesheet jagen und das Ergebnis erst ins Dokument einbauen. Auch hier: Ohne den bisherigen Code zu kennen, kann man Dir nicht wirklich helfen.

                  Wie und wo kann ich diese Zeichenkette sehen? Hier verwirrst du mich!

                  HTML-Datei:

                  <script type="text/javascript" src="ReplaceInnerHTML.js"></script>  
                  <script type="text/javascript">  
                  <!--  
                   function CreateContent()  
                   {  
                    ReplaceInnerHTML("Target1", "NXT1_FeederReportHead_T.xml", "FeederReportHead.xsl");  
                    ReplaceInnerHTML("Target2", "NXT1_FeederReportUnit_T.xml", "FeederReportUnit.xsl");  
                   }  
                  -->  
                  </script>  
                    
                  <body onload="CreateContent()">  
                  <img class="logo" src="..\img\logo-trw-120x.jpg" width="120">  
                  <h1>Feeder Setup Report</h1>  
                  <blockquote>  
                   <hr>  
                   <div id="Target1"></div>  
                   <hr>  
                   <div id="Target2"></div>  
                   <hr>  
                  </blockquote>
                  

                  Grundsätzlich: weder XML noch XSL stammen von mir. Ich erweitere das XSL nur um Darstellungsdetails und/ oder Abfragen.
                  Das XML kann ich nicht ändern.
                  Die HTML-Datei, die das XML vis JS einbindet kann ich nicht ändern.
                  Die JS-Datei könnte ich ändern (möchte möglichst nicht)
                  Ich ändere bis jetzt ausschließlich XSL und eine bis dato nicht erwähnte CSS.

                  bydey

                  --
                  -- bydey ist die Signatur und Verabschiedung, nicht der Nick --
                  -- Navigate all your PHP web projects with  PHP Project Browser--
                  1. Hallo dey,

                    Sehe ich das richtig, dass Du nach der zweiten generierten Spalte sortieren willst?
                    Ja

                    Du denkst viel zu kompliziert. :-)

                    Du definierst Dir ja bereits einen <xsl:key />, Du brauchst eigentlich nur das Ergebnis davon zählen und in ein <xsl:sort /> packen, Dein $qtyreels vereinfacht sich so genauso:

                    <xsl:for-each select="...">  
                      <xsl:sort select="count(key('partnumbers', fsPartNum))" order="descending" />  
                      <xsl:variable name="qtyreels" select="count(key('partnumbers', fsPartNum))" />  
                      ...  
                    </xsl:for-each>
                    

                    Und statt sum(//FeederReportUnit/Unit[fsPartNum = $tmp_fsPartNum]/fsPartQty) kannst Du auch gleich sum(key('partnumbers', fsPartNum)/fsPartQty) machen.

                    [XSLT-Prozessor-Aufruf]
                    Wie und wo kann ich diese Zeichenkette sehen? Hier verwirrst du mich!

                    Oh, Du lässt das über eine PI transformieren. Ich dachte, Du lädst XSLT und XML separat per Javascript und rufst die Transformation dann in JS auf, machst Du aber offensichtlich nicht. Das ist jedoch sowieso egal, weil man das Problem auch in reinem XSLT lösen kann.

                    Viele Grüße,
                    Christian

                    1. Hallo,

                      Du denkst viel zu kompliziert. :-)

                      Du definierst Dir ja bereits einen <xsl:key />, Du brauchst eigentlich nur das Ergebnis davon zählen und in ein <xsl:sort /> packen, Dein $qtyreels vereinfacht sich so genauso:

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

                      <xsl:sort select="count(key('partnumbers', fsPartNum))" order="descending" />
                        <xsl:variable name="qtyreels" select="count(key('partnumbers', fsPartNum))" />
                        ...
                      </xsl:for-each>

                      
                      >   
                      > Und statt sum(//FeederReportUnit/Unit[fsPartNum = $tmp\_fsPartNum]/fsPartQty) kannst Du auch gleich sum(key('partnumbers', fsPartNum)/fsPartQty) machen.  
                        
                      Von den Möglichkeiten des key habe ich bisher nichts gewusst (ausser Gruppieren, und hier habe ich das wie auch nicht verstanden, sondern nur kopiert und probiert). Da werde ich mich noch einmal intensiv mit beschäftigen.  
                        
                      bydey
                      
                      -- 
                      \-- bydey ist die Signatur und Verabschiedung, nicht der Nick --  
                        
                      \-- Navigate all your PHP web projects with  [PHP Project Browser](http://deynews.de/ppb/)--