Mathias: Nummer zusammen bauen

Hallo,

habe ein verschachteltes XML (siehe Beispiel 1) und möchte es in eine flache Struktur bingen (siehe Beispiel 2). Klappt soweit bis auf die Teilenummer. In der Ursprungs-Datei ist die Teilenummer auf die Hierachieebene aufgesplittet. Im Ziel-XMl sollen muss sie wieder komplett sein. Bin XSL-Anfänger und konnte bisher im Internet nichts vergleichbares finden, was mir weitergeholfen hätte. Bin für jeden Gedankenanreiz dankbar!

P.S.: Nein - die Teilenummer steht nicht wie hier im Beispiel im <infos>-Tag. Ist nur der besseren Übersicht wegen... Sie steht nur als Attribut unter Teil.

Beispiel1:

<text>abc</text>
<teil nr="1">
<infos>infos zu teil 1</infos>
   <text>abc</text>
   <teil nr="10">
   <infos>infos zu teil 1.10</infos>
      <text>abc</text>
      <teil nr="10">
      <infos>infos zu teil 1.10.10</infos>
      </teil>
   </teil>
   <teil nr="20">
   <infos>infos zu teil 1.20</infos>
   </teil>
</teil>
<teil nr="2">
<infos>infos zu teil 2</infos>
</teil>
<text>abc</text>
<teil nr="3">
<infos>infos zu teil 3</infos>
   <teil nr="10">
   <infos>infos zu teil 3.10</infos>
   </teil>
</teil>

Beispiel2:

<teil>
   <text>abc</text>
   <nr>1</nr>
   <infos>infos</infos>
</teil>
<teil>
   <text>abc</text>
   <nr>1.10</nr>
   <infos>infos</infos>
</teil>
<teil>
   <text>abc</text>
   <nr>1.10.10</nr>
   <infos>infos</infos>
</teil>
<teil>
   <nr>1.20</nr>
   <infos>infos</infos>
</teil>
<teil>
   <nr>2</nr>
   <infos>infos</infos>
</teil>
<teil>
   <text>abc</text>
   <nr>3</nr>
   <infos>infos</infos>
</teil>
<teil>
   <nr>3.10</nr>
   <infos>infos</infos>
</teil>

Mathias

  1. Tach Mathias,

    Bin XSL-Anfänger und konnte bisher im Internet nichts vergleichbares finden, was mir weitergeholfen hätte. Bin für jeden Gedankenanreiz dankbar!

    Das folgende Stylesheet verarbeitet alle teil-Elemente im Dokument:

    <?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"/>  
      
    <xsl:template match="/">  
      <teile_neu>  
        <xsl:apply-templates select="//teil"/>  
      </teile_neu>  
    </xsl:template>  
      
    <xsl:template match="teil">  
      <teil>  
        <text><xsl:value-of select="text"/></text>  
        <nr><xsl:value-of select="@nr"/></nr>  
        <infos><xsl:value-of select="infos"/></infos>  
      </teil>  
    </xsl:template>  
      
    </xsl:stylesheet>
    

    Man liest sich,
    svg4you

    1. Hi svg4you,

      Danke für dein Antwort, das ist aber nicht das was ich meinte [ das hätte ich auch noch hinbekommen ;-)]. Vielleicht hab ich mit etwas zu umständlich ausgedrückt:

      das Problem ist nicht einfach das Attribut Nr auszulesen, sondern das Zusammenbauen der neuen Nr, welche aus den einzelnen Attributen Nr der vorigen Ebene besteht:

      <teil1 Nr1/>                   1. Ebene
          <teil2 Nr10/>              2. Ebene
              <teil3 Nr10/>          3. Ebene
          <teil4 Nr20>               2. Ebene
      <teil5 Nr2>                    1. Ebene
      <teil6 Nr3>                    1. Ebene
          <teil7 Nr10/>              2. Ebene
          <teil8 Nr20/>              2. Ebene

      Soll ergeben:

      <teil_neu nr1 />
      <teil_neu nr1.10 />
      <teil_neu nr1.10.10 />
      <teil_neu nr1.10.20 />
      <teil_neu nr2 />
      <teil_neu nr3 />
      <teil_neu nr3.10 />
      <teil_neu nr3.20 />

      Konkret: mein XML:

      BoQCtgy sind die Teile. RNoPart ist die Teilenummer. In der letzten Hierarchieebene BoQCtgy=Item. Insgesamt können es bis zu 7 Hierarchiestufen sein.

      <?xml version="1.0" encoding="UTF-8" ?>

      • <GAEB>
      • <GAEBInfo>
      • <PrjInfo>
      • <Award>
          + <AwardInfo>
          - <BoQ>
            - <BoQBody>
              + <Remark>
              - <BoQCtgy RNoPart="1">
                + <LblTx>
                - <BoQBody>
                  - <BoQCtgy RNoPart="10">
                  + <LblTx>
                    - <BoQBody>
                      - <BoQCtgy RNoPart="10">
                        - <BoQBody>
                          - <Itemlist>
                            + <Item ID="BPNABIDI" RNoPart="10">
                            + <Item ID="BPNABNFI" RNoPart="20">
                            </Itemlist>
                          </BoQBody>
                        </BoQCtgy>
                      </BoQBody>
                    </BoQCtgy>
                  </BoQBody>
                </BoQCtgy>
              </BoQBody>
          </BoQ>
          </Award>
          </GAEB>

      Soll ergeben:
      <Teil Nr 1/>
      <Teil Nr 1.10/>
      <Teil Nr 1.10.10/>
      <Teil Nr 1.10.10.10/>
      <Teil Nr 1.10.10.20/>

      1. Tach Mathias,

        das Problem ist nicht einfach das Attribut Nr auszulesen, sondern das Zusammenbauen der neuen Nr, welche aus den einzelnen Attributen Nr der vorigen Ebene besteht:

        Liefere mal wohlgeformten XML-Daten, dann schaue ich nochmal drüber.

        Man liest sich,
        svg4you

        1. Hi svg4you,

          hier das wohlgeformte XML
          <?xml version="1.0" encoding="UTF-8" ?>
          <GAEB>
          <GAEBInfo/>
          <PrjInfo/>
          <Award>
          <AwardInfo/>
          <BoQ>
          <BoQBody>
          <Remark/>
          <BoQCtgy RNoPart="1">
          <LblTx/>
          <BoQBody>
          <BoQCtgy RNoPart="10">
          <LblTx/>
          <BoQBody>
          <BoQCtgy RNoPart="10">
          <BoQBody>
          <Itemlist>
          <Item ID="BPNABIDI" RNoPart="10"/>
          <Item ID="BPNABNFI" RNoPart="20"/>
          </Itemlist>
          </BoQBody>
          </BoQCtgy>
          </BoQBody>
          </BoQCtgy>
          </BoQBody>
          </BoQCtgy>
          </BoQBody>
          </BoQ>
          </Award>
          </GAEB>

          Falls es interessiert, hier gibt's ein etwas größerers Beispiel:
          http://www.gaeb-da-xml.de/content/version30/Musterdateien/2004-001.X81

          Vielen Dank für deine Mühe.
          Cheers Mathias

          1. Tach Mathias,

            hier das wohlgeformte XML
            ...

            Mit diesem Ansatz

            <xsl:template match="/">  
              <teile_neu>  
                <xsl:apply-templates select="//BoQCtgy"/>  
              </teile_neu>  
            </xsl:template>  
              
              
            <xsl:template match="BoQCtgy">  
              
              <xsl:variable name="nr">  
                <xsl:for-each select="ancestor-or-self::BoQCtgy">  
                  <xsl:value-of select="@RNoPart"/>  
                   <xsl:if test="position() != last()"><xsl:text>.</xsl:text></xsl:if>  
                </xsl:for-each>  
              </xsl:variable>  
              
              <teil nr="{$nr}"/>  
              
            </xsl:template>
            

            komme ich bis zu

            <?xml version="1.0" encoding="ISO-8859-1"?>  
            <teile_neu>  
             <teil nr="1"/>  
             <teil nr="1.10"/>  
             <teil nr="1.10.10"/>  
            </teile_neu>
            

            Da müssten wohl noch die Bezüge zu BoQBody und Itemlist/Item hinein.

            Man liest sich,
            svg4you

            1. Hi svg4you,

              Funktioniert bei mir! War auf nem ganz anderen Weg, der aber leider nicht geklappt hat. Habe deinen Vorschlag nun benutzt:

              <xsl:template match="BoQBody">
                <xsl:call-template name="pos_tree_in">
                </xsl:call-template>
              </xsl:template>

              <xsl:template name="pos_tree_in">
                <xsl:if test="BoQCtgy">
                  <xsl:for-each select="BoQCtgy">
                    <ENTITY>
               <xsl:if test="name(preceding-sibling::*[1]) = 'Remark'">
                 <LANG><xsl:value-of select="preceding-sibling::*[1]/Description/CompleteText/DetailTxt/Text"/></LANG>
                 <KURZ><xsl:value-of select="preceding-sibling::*[1]/Description/CompleteText/OutlineText/OutlTxt/TextOutlTxt"/></KURZ>
               </xsl:if>
               <xsl:variable name="nr">
                 <xsl:for-each select="ancestor-or-self::BoQCtgy">
                   <xsl:value-of select="@RNoPart"/>
                   <xsl:if test="position() != last()">xsl:text.</xsl:text></xsl:if>                 </xsl:for-each>
                      </xsl:variable>
               <NUMB><xsl:value-of select="$nr" /></NUMB>    <LBLTX><xsl:value-of select="LblTx"/></LBLTX>
               <ITEM>No</ITEM>
                    </ENTITY>
                    <xsl:apply-templates select="BoQBody"/>
                  </xsl:for-each>
                </xsl:if>
                <xsl:if test="Itemlist">
                  <xsl:for-each select="Itemlist/Item">
                    <ENTITY>
               <xsl:variable name="nr">
                 <xsl:for-each select="ancestor::BoQCtgy">
                          <xsl:value-of select="@RNoPart"/>
                   <xsl:if test="position() != last()">xsl:text.</xsl:text></xsl:if>
                 </xsl:for-each>
                 <xsl:if test="ancestor::BoQCtgys">xsl:text.</xsl:text></xsl:if>
                 <xsl:for-each select="ancestor-or-self::Item">
                   <xsl:value-of select="@RNoPart"/>
                   <xsl:if test="position() != last()">xsl:text.</xsl:text></xsl:if>
                 </xsl:for-each>
               </xsl:variable>
               <NUMB><xsl:value-of select="$nr" /></NUMB>
               <LBLTX><xsl:value-of select="LblTx"/></LBLTX>
               <ITEM>Yes</ITEM>
               <QTY><xsl:value-of select="Qty"/></QTY>
               <PREDOTY><xsl:value-of select="PredQty"/></PREDOTY>
               <QU><xsl:value-of select="QU"/></QU>
                    </ENTITY>
                  </xsl:for-each>
                </xsl:if>
              </xsl:template>

              Bestimmt könnte ich die Prüfung auf BoQCtgy und Item noch etwas eleganter umsetzen, abr ich bin nur froh das es funktioniert.

              Vielen vielen Dank!!!!!

              Grüße
              Mathias