2017-04-26 5 views
0

Ich bin ein XML-Dokument, welches ich mit XSLT-Transformation 1.0:XSLT 1.0 - Gruppieren von komplexen verschachtelten Elementen mit Attributen

<?xml version="1.0" encoding="UTF-8"?> 
<element tag="container"> 
    <data handle="$1"> 
     ... 
    </data> 
    <assignments/> 
    <expression context="$1"> 
     Object_Text 
    </expression> 
    <expression context="$1"> 
     Object_Text 
    </expression> 
    <expression context="$1"> 
     Object_Heading 
    </expression> 
    <element tag="container"> 
     <data handle="$2"> 
      ... 
     </data> 
     <assignments/> 
     <element tag="container"> 
      <data handle="$3"> 
       ... 
      </data> 
      <assignments/> 
      <expression context="$3"> 
       Object_Text 
      </expression> 
     </element> 
     <element tag="container"> 
      ... 
     </element> 
    </element> 
    <element tag="container"> 
     <element tag="container"> 
      <element tag="container"> 
       <expression context="$1"> 
        Object_Text 
       </expression> 
      </element> 
     </element> 
    </element> 
    <element tag="container"> 
    <expression context="$1"> 
     Object_Identifier 
    </expression> 
    </element> 
</element> 

Ich habe für jeden Ausdruckstyp Zuweisungen hinzufügen (Object_Text, Object_Heading, ...) zum Tag des nächsten übergeordneten Container-Knotens, der ein Tag enthält (nicht alle Container haben dieses Tag, diese sollten ignoriert werden) und der Kontextwert des Ausdrucks muss mit dem Handle-Wert des Containers übereinstimmen. Aufgrund der Tatsache, dass ich für jeden Ausdruckstyp eine Zuweisung benötige, sollte ich nur eine Zuweisung für jeden Typ in seinem Kontext haben, egal wie viel es erscheint. So ist die gewünschte Ausgabe ist:

<?xml version="1.0" encoding="UTF-8"?> 
<element tag="container"> 
    <data handle="$1"> 
     ... 
    </data> 
    <assignments> <!--Added assignments here (one for each type with @context='$1')--> 
     <assignment name="Object_Text"> 
     </assignment> 
     <assignment name="Object_Heading"> 
     </assignment> 
     <assignment name="Object_Identifier"> 
     </assignment> 
    </assignments> 
    <expression context="$1"> 
     Object_Text 
    </expression> 
    <expression context="$1"> 
     Object_Text 
    </expression> 
    <expression context="$1"> 
     Object_Heading 
    </expression> 
    <element tag="container"> 
     <data handle="$2"> 
      ... 
     </data> 
     <assignments/> 
     <element tag="container"> 
      <data handle="$3"> 
       ... 
      </data> 
      <assignments> <!--Added assignments here (one for each type with @context='$3')--> 
       <assignment name="Object_Text"> 
       </assignment> 
      </assignments> 
      <expression context="$3"> 
       Object_Text 
      </expression> 
     </element> 
     <element tag="container"> 
      ... 
     </element> 
    </element> 

    <element tag="container"> 
    <expression context="$1"> 
     Object_Identifier 
    </expression> 
    </element> 
</element> 

Derzeit ich bin in der Lage eine Gruppe von Ausdruckstyp (Object_Text, etc.) mit Muench-Gruppierung Methode zu erhalten. Aber mein Problem ist, dass ich diese Ausdruckstypen nicht durch ihr Attribut @context unterscheiden kann, so dass der Container nur Zuordnungen für die richtigen Ausdrücke enthält, die er wirklich mit demselben @ context enthält.

Ich bin dankbar für jede Hilfe. Kennt jemand einen Weg, um die gewünschte Leistung zu erreichen? Ich habe viele Dinge ausprobiert, aber momentan fehlt es an Erfahrung/Wissen für diese Aufgabe.

EDIT: Es sollte hinzugefügt werden, dass dies eine Beispielstruktur für ein XML-Dokument ist. Daher sollten die XSLT-Funktionen Ausdrücke in beliebig verschachtelten, umhüllten Strukturen und beliebig oft erkennen.

Antwort

0

Lassen Sie uns, indem er erklärt einen Schlüssel für Ausdrücke

<xsl:key name="kExp" match="expression" use="concat(@context, '|', normalize-space(.))"/> 

unter assignments Knoten starten, werden wir das @handle Attribut des ersten voraus-Geschwisterknoten data

<xsl:variable name="dataHandle" select="preceding-sibling::data/@handle"/> 

wenn dieser Ort Variable wird im assignments Knoten verwendet und mit Muenchian Methode (Ich habe angenommen, dass die expre ssions sind Geschwister oder Nachkommen der Geschwister der Knoten assignments):

<xsl:template match="assignments"> 
     <xsl:variable name="dataHandle" select="preceding-sibling::data/@handle"/> 
     <xsl:copy> 
      <xsl:for-each select="../descendant::expression[@context=$dataHandle 
            and generate-id()=generate-id(key('kExp', concat(@context, '|', normalize-space(.)))[1])]"> 
       <assignment name="{normalize-space(.)}"></assignment> 
      </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 

Das gesamte Sheet ist unten:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes"/> 

    <xsl:key name="kExp" match="expression" use="concat(@context, '|', normalize-space(.))"/> 


    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="assignments"> 
     <xsl:variable name="dataHandle" select="preceding-sibling::data/@handle"/> 
     <xsl:copy> 
      <xsl:for-each select="../descendant::expression[@context=$dataHandle 
            and generate-id()=generate-id(key('kExp', concat(@context, '|', normalize-space(.)))[1])]"> 
       <assignment name="{normalize-space(.)}"></assignment> 
      </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

sehen sie in Aktion in http://xsltransform.net/a9Giwr.

+0

Vielen Dank für Ihre Antwort, diese hat mir wirklich geholfen und mir die richtigen Tipps gegeben, um mit meiner Arbeit voranzukommen! –

0

Dies wird Sie in Fahrt bringen. Sie haben etwas Unterdrückung, die dieser Code nicht berücksichtigt.

<!-- Handle each container that has an assignments node. --> 
    <xsl:template match="element[@tag='container' and .//assignments]"> 
    <!-- Bind to the expressions for this container. --> 
    <xsl:variable name="expressions" select="expression"/> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"> 
     <xsl:with-param name="expressions" select="$expressions"/> 
     </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:template> 

    <!-- Create the assignments for each container. --> 
    <xsl:template match="assignments"> 
    <xsl:param name="expressions"/> 
    <xsl:copy> 
     <xsl:for-each select="$expressions"> 
     <xsl:element name="assignment"> 
      <xsl:attribute name="name"> 
      <xsl:value-of select="normalize-space(.)"/> 
      </xsl:attribute> 
     </xsl:element> 
     </xsl:for-each> 
    </xsl:copy> 
    </xsl:template> 

    <!-- Identity template. --> 
    <xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/>   
    </xsl:copy> 
    </xsl:template> 
Verwandte Themen