Jens Nonnewitz: Generate IDs nach SNMP-MIB Prinzip

Moin,

ich möchte gern, dass jeder Node des XML-Files eine eindeutige ID bekommt, die dem Schema vom SNMP-MIB entspricht.

  
<xml>  
<fnode>  
   <table>  
     <thead>  
     </thead>  
     <tbody>  
      .....  
     </tbody>  
   </table>  
   <sfnode>  
   </sfnode>  
</fnode>  
<fnode2>  
</fnode2>  
</xml>  

"<fnode2>" soll als Id = 2 erhalten.
"<fnode>" soll als ID = 1 erhalten.
"<fnode><table>" soll als ID = 1.1 erhalten
"<fnode><sfnode>" soll als ID = 1.2 erhalten, da es sich um das zweite Item in dieser Tiefe des Baumes handelt.

  
<xsl:template match="tbody">  
  <tbody>  
  
  </tbody>  
  </xsl:template>  

Wie kann ich z.B. bei diesem <tbody> erreichen, dass es die ID = 1.1.2 bekommt?

Gruß
Jens

  1. Hallo Jens,

    ich möchte gern, dass jeder Node des XML-Files eine eindeutige ID bekommt, die dem Schema vom SNMP-MIB entspricht.

    Probiere es so (root entspricht dem Wurzelelement, welches offenbar kein id-Attribut erhalten soll):

    <?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" version="1.0" encoding="UTF-8" indent="yes"/>  
      
      <xsl:template match="@* | node()">  
        <xsl:copy>  
          <xsl:apply-templates select="@* | node()"/>  
        </xsl:copy>  
      </xsl:template>  
      
      <xsl:template match="root//*">  
        <xsl:element name="{name()}">  
          <xsl:attribute name="id">  
            <xsl:number count="root//*" format="1" level="multiple"/>  
          </xsl:attribute>  
          <xsl:apply-templates select="@* | node()"/>  
        </xsl:element>  
      </xsl:template>  
      
    </xsl:stylesheet>
    

    Grüße,
    Thomas

    1. Hi Thomas,

      funktioniert bereits super. Wie müsste ich den Code umändern, damit das Root-Item auch mit einbezogen wird?

      Und da hab ich noch eine kleine Frage. Wie schafft man es, dass das ganze XML File von dieser Nummerierung betroffen ist, auch wenn ich z.B. nicht alles im XSL davon darstellen möchte?

        
      <?xml version="1.0"?>  
      <root>  
       <fnode>  
         <table>  
           <thead>  
           </thead>  
           <tbody>  
            .....  
           </tbody>  
         </table>  
         <sfnode>  
         </sfnode>  
       </fnode>  
       <fnode2>  
       </fnode2>  
      </root>  
        
      
      
        
      <xsl:template match="/">  
          <html>  
            <head>  
              <title>Ausgabe</title>  
            </head>  
            <body>  
                <xsl:apply-templates select="root/fnode/table"/>  
            </body>  
          </html>  
        </xsl:template>  
        
      
      
      1. Hi Thomas,

        habs gerade herausgefunden: einfach //* statt root//*.

        Jetzt besitzen alle Nodes die richtigen IDs aber ich kann leider keine Tabelle zeichnen, weil sich das scheinbar gegenseitig irgendwie im Weg steht. Wahrscheinlich muss ich die Tabelle zeichnen und gleichzeitig die IDs dabei vergeben, oder?

          
         <xsl:template match="/">  
            <html xmlns="http://www.w3.org/1999/xhtml">  
              <head>  
                <title>Ausgabe</title>  
              </head>  
              <body>  
                <div id="wrapper">  
                  <form name="configForm" method="POST" action="/config/ports" onsubmit="return checkForm(this);">  
                    <xsl:apply-templates select="root/fnode/table"/>  
                  </form>  
                </div>  
              </body>  
            </html>  
          </xsl:template>  
          
          <xsl:template match="@* | node()">  
            <xsl:copy>  
              <xsl:apply-templates select="@* | node()"/>  
            </xsl:copy>  
          </xsl:template>  
          
          <xsl:template match="//*">  
            <xsl:element name="{name()}">  
              <xsl:attribute name="id">  
                <xsl:number count="//*" format="1" level="multiple"/>  
              </xsl:attribute>  
              <xsl:apply-templates select="@* | node()"/>  
            </xsl:element>  
          </xsl:template>  
          
          <xsl:template match="table">  
            <table border="1" frame="border" rules="all">  
          
              <xsl:apply-templates select="./tthead"/>  
              <xsl:apply-templates select="./ttbody"/>  
          
            </table>  
          </xsl:template>  
          
          
          <xsl:template match="tthead">  
            <thead bgcolor="#787878">  
              <th>  
                <xsl:value-of select="port_th"/>  
              </th>  
              <th>  
                <xsl:value-of select="dup_th"/>  
              </th>  
              <th>  
                <xsl:value-of select="speed_th"/>  
              </th>  
              <th>  
                <xsl:value-of select="test_th"/>  
              </th>  
              <th>  
                <xsl:value-of select="sel_th"/>  
              </th>  
              <th>  
                <xsl:value-of select="sel_th"/>  
              </th>  
              <th>  
                <xsl:value-of select="sel_th"/>  
              </th>  
            </thead>  
          </xsl:template>  
          
        
        
        1. Hallo Jens,

          Jetzt besitzen alle Nodes die richtigen IDs aber ich kann leider keine Tabelle zeichnen, weil sich das scheinbar gegenseitig irgendwie im Weg steht. Wahrscheinlich muss ich die Tabelle zeichnen und gleichzeitig die IDs dabei vergeben, oder?

          Mein Ansatz war eine abgewandelte Identitäts-Transformation. Wenn noch HTML im Spiel ist, wäre es hier vielleicht einfacher, das erhaltene Ergebnis weiter zu verarbeiten (nochmal zu transformieren). Ansonsten über die count()-Funktion und Vorgänger-/Nachfahren-Hierarchien probieren, überblicke ich aber beim Gezeigten nicht.

          Grüße,
          Thomas

          1. Hi Thomas

            Mein Ansatz war eine abgewandelte Identitäts-Transformation. Wenn noch HTML im Spiel ist, wäre es hier vielleicht einfacher, das erhaltene Ergebnis weiter zu verarbeiten (nochmal zu transformieren). Ansonsten über die count()-Funktion und Vorgänger-/Nachfahren-Hierarchien probieren, überblicke ich aber beim Gezeigten nicht.

            Hab leider noch nicht so viel Erfahrung mit XSLT. Das erste klingt für mich aber logischer -> nochmals zu transformieren.

            Die komplette Tabelle wird in diesem Template erstellt:

              
            <xsl:template match="table">  
                <table border="1" frame="border" rules="all">  
              
                  <xsl:apply-templates select="./tthead"/>  
                  <xsl:apply-templates select="./ttbody"/>  
              
                </table>  
              </xsl:template>  
            
            

            liege ich in der Annahme richtig, dass ich in dem Template überprüfen muss ob der name == table ist und dann muss das template match="table" aufgerufen werden?

              
            <xsl:template match="//*">  
                <xsl:element name="{name()}">  
                  <!-- id hinzufügen -->  
                  <xsl:attribute name="id">  
                    <xsl:number count="//*" format="1" level="multiple"/>  
                  </xsl:attribute>  
                  <xsl:apply-templates select="@* | node()"/>  
                 <xsl:if test = 'table'>  
                    <xsl:apply-templates select="table"/>  
                  </xsl:if>  
                </xsl:element>  
              </xsl:template>  
            
            

            Oder liege ich mit dieser Annahme noch meilenweit vom richtigen Ergebnis weg.