2017-05-09 2 views
0

Ich habe Probleme, eine Vorlage rekursiv anzuwenden. Ich würde gerne sagen, dass ich, obwohl ich ein paar Mal mit einfachen XSL-Transformationen gearbeitet habe, kein tiefes Wissen über sie habe.xsl apply-templates rekursiv nach der Umwandlung

Ich habe die folgende XML, die

<classes> 
    <class name="A" author="Mr.X" > 
     <attribute name="i_" type="integer" visibility="protected" /> 
     <attribute name="f_" type="float" visibility="private" /> 
     <attribute name="c_" type="char" visibility="private" /> 
     <method name="foo" return="integer" visibility="public" > 
      <param name="a" type="integer" /> 
      <param name="b" type="integer" /> 
     </method> 
    </class> 

    <class name="B" author="Mr.Y" > 
     <attribute name="s_" type="string" visibility="protected" /> 
     <method name="bar" visibility="public" /> 
    </class> 

    <class name="CA" author="Mr.Z" base="A" > 
     <attribute name="d_" type="double" visibility="protected" /> 
    </class> 

    <class name="CB" author="Mr.Z" base="B" /> 

    <class name="DCA" author="Mr.X" base="CA" > 
     <attribute name="s_" type="string" visibility="protected" /> 
    </class> 
</classes> 

und ich würde eine XML erhalten, die die Klassen mit allen Attributen und Methoden enthält, die beide von sich selbst und von dieser Basisklasse Klassen mit Methoden und Attribute repräsentiert gerne , genauso wie die OO-Vererbung funktioniert.

würde Ich mag die folgende XML-

<classes> 
    <class name="A" author="Mr.X" > 
     <attribute name="i_" type="integer" visibility="protected" /> 
     <attribute name="f_" type="float" visibility="private" /> 
     <attribute name="c_" type="char" visibility="private" /> 
     <method name="foo" return="integer" visibility="public" > 
      <param name="a" type="integer" /> 
      <param name="b" type="integer" /> 
     </method> 
    </class> 

    <class name="B" author="Mr.Y" > 
     <attribute name="s_" type="string" visibility="protected" /> 
     <method name="bar" visibility="public" /> 
    </class> 

    <class name="CA" author="Mr.Z" > 
     <attribute name="d_" type="double" visibility="protected" /> 
     <!--[begin] inherited from base class A by Mr.X--> 
     <attribute name="i_" type="integer" visibility="protected" /> 
     <attribute name="f_" type="float" visibility="private" /> 
     <attribute name="c_" type="char" visibility="private" /> 
     <method name="foo" return="integer" visibility="public" > 
      <param name="a" type="integer" /> 
      <param name="b" type="integer" /> 
     </method> 
     <!--[end] inherited from base class A--> 
    </class> 

    <class name="CB" author="Mr.Z" > 
     <!--[begin] inherited from base class B by Mr.Y--> 
     <attribute name="s_" type="string" visibility="protected" /> 
     <method name="bar" visibility="public" /> 
     <!--[end] inherited from base class B--> 
    </class> 

    <class name="DCA" author="Mr.X" > 
     <attribute name="s_" type="string" visibility="protected" /> 
     <!--[begin] inherited from base class CA by Mr.Z--> 
     <attribute name="d_" type="double" visibility="protected" /> 
     <!--[begin] inherited from base class A by Mr.X--> 
     <attribute name="i_" type="integer" visibility="protected" /> 
     <attribute name="f_" type="float" visibility="private" /> 
     <attribute name="c_" type="char" visibility="private" /> 
     <method name="foo" return="integer" visibility="public" > 
      <param name="a" type="integer" /> 
      <param name="b" type="integer" /> 
     </method> 
     <!--[end] inherited from base class A--> 
     <!--[end] inherited from base class CA--> 
    </class> 
</classes> 

Ich schrieb das folgende XSL erhalten, funktioniert aber nur für eine Ebene der Klassenvererbung.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" encoding="ISO-8859-1" indent="yes"/> 

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

    <xsl:template match="/classes/import"> 
     <xsl:comment>importing <xsl:value-of select="@file"/> file</xsl:comment> 
     <xsl:apply-templates select="document(@file)/classes/node()" /> 
    </xsl:template> 

    <xsl:template match="*[@base]"> 
     <xsl:variable name="bc" select="@base" /> 
     <xsl:copy> 
      <xsl:apply-templates select="@*[name(.)!='base']"/>      
      <xsl:apply-templates select="/classes/class[@name=$bc]/@*[name(.)!='name' and name(.)!='author']" /> 
      <xsl:apply-templates /> 
      <xsl:comment>[begin] inherited from base class <xsl:value-of select="$bc"/> by <xsl:value-of select="//class[@name=$bc]/@author"/></xsl:comment> 
      <xsl:apply-templates select="/classes/class[@name=$bc]/node()" /> 
      <xsl:comment>[end] inherited from base class <xsl:value-of select="$bc"/></xsl:comment> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Natürlich, wenn ich die obige Transformation so oft wie die maximale Höhe der Vererbung gelten, dass die Klassen, ich (fast) erhalten das gewünschte Ergebnis, aber mein Ziel ist es, in nur einer Transformation zu erhalten .

Jeder Leitfaden würde sehr geschätzt werden. Danke im Voraus.

+1

Ihr erstes Problem ist mehr als genug für eine Frage. Bitte posten Sie Ihre andere Frage separat. –

+0

Ich bearbeite die Frage, um sie zu teilen, und ich werde die zweite in einem anderen Beitrag veröffentlichen. – hmb

Antwort

0

Hier ist, wie Sie Ihr erstes Problem zu nähern:

XSLT 1,0

<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:strip-space elements="*"/> 

<xsl:key name="parent" match="class" use="@name" /> 

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

<xsl:template match="class"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <xsl:apply-templates select="key('parent', @base)" mode="inherit"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="class" mode="inherit"> 
    <xsl:comment> 
     <xsl:text>[begin] inherited from class </xsl:text> 
     <xsl:value-of select="@name"/> 
    </xsl:comment> 
    <xsl:copy-of select="attribute | method"/> 
    <xsl:apply-templates select="key('parent', @base)" mode="inherit"/> 
    <xsl:comment> 
     <xsl:text>[end] inherited from class </xsl:text> 
     <xsl:value-of select="@name"/> 
    </xsl:comment> 
</xsl:template> 

</xsl:stylesheet> 

auf Ihre Eingabe Beispiel angewandt wird, wird das Ergebnis sein:

<?xml version="1.0" encoding="UTF-8"?> 
<classes> 
    <class name="A" author="Mr.X"> 
    <attribute name="i_" type="integer" visibility="protected"/> 
    <attribute name="f_" type="float" visibility="private"/> 
    <attribute name="c_" type="char" visibility="private"/> 
    <method name="foo" return="integer" visibility="public"> 
     <param name="a" type="integer"/> 
     <param name="b" type="integer"/> 
    </method> 
    </class> 
    <class name="B" author="Mr.Y"> 
    <attribute name="s_" type="string" visibility="protected"/> 
    <method name="bar" visibility="public"/> 
    </class> 
    <class name="CA" author="Mr.Z" base="A"> 
    <attribute name="d_" type="double" visibility="protected"/> 
    <!--[begin] inherited from class A--> 
    <attribute name="i_" type="integer" visibility="protected"/> 
    <attribute name="f_" type="float" visibility="private"/> 
    <attribute name="c_" type="char" visibility="private"/> 
    <method name="foo" return="integer" visibility="public"> 
     <param name="a" type="integer"/> 
     <param name="b" type="integer"/> 
    </method> 
    <!--[end] inherited from class A--> 
    </class> 
    <class name="CB" author="Mr.Z" base="B"> 
    <!--[begin] inherited from class B--> 
    <attribute name="s_" type="string" visibility="protected"/> 
    <method name="bar" visibility="public"/> 
    <!--[end] inherited from class B--> 
    </class> 
    <class name="DCA" author="Mr.X" base="CA"> 
    <attribute name="s_" type="string" visibility="protected"/> 
    <!--[begin] inherited from class CA--> 
    <attribute name="d_" type="double" visibility="protected"/> 
    <!--[begin] inherited from class A--> 
    <attribute name="i_" type="integer" visibility="protected"/> 
    <attribute name="f_" type="float" visibility="private"/> 
    <attribute name="c_" type="char" visibility="private"/> 
    <method name="foo" return="integer" visibility="public"> 
     <param name="a" type="integer"/> 
     <param name="b" type="integer"/> 
    </method> 
    <!--[end] inherited from class A--> 
    <!--[end] inherited from class CA--> 
    </class> 
</classes> 

ich nicht lesen Ihre zweite Frage.

+0

Danke Michael. Es funktioniert gut für den ersten Teil der Frage, aber wie der zweite Teil sagt, ich importiere Daten von einem externen XML, und soweit ich weiß, funktioniert die Verwendung von Schlüsseln in dieser Situation nicht. – hmb

+0

Gibt es eine andere Möglichkeit, diese Art von Transformation ohne Verwendung von Schlüsseln durchzuführen? – hmb

+0

Der Begriff [import] (https://www.w3.org/TR/xslt/#import) wird bereits in XSLT zum Importieren eines anderen ** Stylesheets ** verwendet. Sie "importieren" keine Daten und verweisen lediglich auf ein anderes XML-Dokument. Und Sie * können * Schlüssel in einem anderen Dokument verwenden, vorausgesetzt, Sie (in XSLT 1.0) wechseln Sie zuerst den Kontext zu diesem Dokument. Sie können auch ein Prädikat anstelle eines Schlüssels verwenden: Verwenden Sie zum Beispiel '' in Das obige Stylesheet würde dasselbe erreichen, wenn auch weniger effizient. –

Verwandte Themen