2017-05-16 59 views
0

我想將表示類及其基類的XML轉換爲包含其自己的方法和屬性的類以及所有基類的方法和屬性,因爲OO繼承是可行的。外部數據中的XSL apply-template

爲一個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" 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> 

應轉化爲

<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 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 class A--> 
    </class> 
    <class name="CB" author="Mr.Z"> 
    <!--[begin] inherited from class B by Mr.Y--> 
    <attribute name="s_" type="string" visibility="protected"/> 
    <method name="bar" visibility="public"/> 
    <!--[end] inherited from class B--> 
    </class> 
    <class name="DCA" author="Mr.X"> 
    <attribute name="s_" type="string" visibility="protected"/> 
    <!--[begin] inherited from class CA by Mr.Z--> 
    <attribute name="d_" type="double" visibility="protected"/> 
    <!--[begin] inherited from 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 class A--> 
    <!--[end] inherited from class CA--> 
    </class> 
</classes> 

隨着Michael的幫助下,我有以下的XSL如果所有的類在定義工作正常相同的XML文件。

<?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" encoding="ISO-8859-1" 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="@*[name()!='base']|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:text> by </xsl:text> 
      <xsl:value-of select="@author"/> 
     </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> 

或下面的等價但沒有鍵的轉換。現在

<?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" encoding="ISO-8859-1" indent="yes"/> 

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

    <!-- 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="@*[name()!='base']|node()"/> 
      <xsl:apply-templates select="//class[@name=current()/@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:text> by </xsl:text> 
      <xsl:value-of select="@author"/> 
     </xsl:comment> 
     <xsl:copy-of select="attribute | method"/> 
     <xsl:apply-templates select="//class[@name=current()/@base]" mode="inherit"/> 
     <xsl:comment> 
      <xsl:text>[end] inherited from class </xsl:text> 
      <xsl:value-of select="@name"/> 
     </xsl:comment> 
    </xsl:template> 

</xsl:stylesheet> 

,我想處理這些類可以是可以在主XML或其它XML文件中定義,與進口元件的其他文件鏈接,這意味着外部XML可以可以像使用主XML一樣使用。

表示這些類的簡化XML可以是

<classes>  
    <import file="c2.xml" /> 

    <class name="XZ" author="Mr.B" base="Z"> 
     <method name="foo" visibility="public" /> 
    </class> 
</classes> 

和c2.xml的內容可以是

<classes> 
    <class name="Z" author="Mr.A" > 
     <attribute name="i_" type="integer" visibility="protected" /> 
    </class> 
</classes> 

和期望輸出將是

<classes> 
    <class name="Z" author="Mr.A"> 
    <attribute name="i_" type="integer" visibility="protected"/> 
    </class> 
    <class name="XZ" author="Mr.B"> 
    <method name="foo" visibility="public"/> 
    <!--[begin] inherited from class Z by Mr.A--> 
    <attribute name="i_" type="integer" visibility="protected"/> 
    <!--[end] inherited from class Z--> 
    </class> 
</classes> 

的新的XSL與上面的XSL非常相似,但添加了以下模式,以便處理新的問題元件

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

所以,XSL就會像下面一個使用按鍵

<?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" encoding="ISO-8859-1" 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="/classes/import"> 
     <xsl:comment> 
      <xsl:text>importing </xsl:text> 
      <xsl:value-of select="@file"/> 
      <xsl:text> file</xsl:text> 
     </xsl:comment> 
     <xsl:apply-templates select="document(@file)/classes/node()" /> 
    </xsl:template> 

    <xsl:template match="class"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*[name()!='base']|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:text> by </xsl:text> 
      <xsl:value-of select="@author"/> 
     </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> 

或類似以下在沒有鍵被用來

<?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" encoding="ISO-8859-1" indent="yes"/> 

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

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

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

    <xsl:template match="class"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*[name()!='base']|node()"/> 
      <xsl:apply-templates select="//class[@name=current()/@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:text> by </xsl:text> 
      <xsl:value-of select="@author"/> 
     </xsl:comment> 
     <xsl:copy-of select="attribute | method"/> 
     <xsl:apply-templates select="//class[@name=current()/@base]" mode="inherit"/> 
     <xsl:comment> 
      <xsl:text>[end] inherited from class </xsl:text> 
      <xsl:value-of select="@name"/> 
     </xsl:comment> 
    </xsl:template> 

</xsl:stylesheet> 

變換與進口關聯的時對於在外部文件中定義的類而言,元素正常工作,但基類繼承行爲不適用於這些類。

的(錯誤)輸出,以上述XSL和以前的XML(包括c2.xml文件中的)

<classes> 
    <!--importing c2.xml file--> 
    <class name="Z" author="Mr.A"> 
    <attribute name="i_" type="integer" visibility="protected"/> 
    </class> 
    <class name="XZ" author="Mr.B"> 
    <method name="foo" visibility="public"/> 
    </class> 
</classes> 

請注意,XZ類不包括方法,並從其基本屬性Z類

注意外部XML文件可能還包括進口元件

我已經嘗試了兩種不同的方法。第一個是爲類使用鍵,包括那些在外部XML文件中聲明的鍵。我失敗了,因爲我事先不知道外部文件名,以便爲在這些外部XML文件中定義的類生成密鑰。第二個是應用「繼承」模式謂詞,但是我又失敗了,因爲我不知道外部文件名以便爲所有文件應用帶有繼承模式的模板類。

任何有關如何應用「繼承」模板的外部數據類的幫助將非常感激。任何有或沒有鑰匙的方法都適合我。

在此先感謝。

回答

0

鍵只能在單個文檔中使用。我建議兩種方法:

(a)首先將所有文檔合併爲一個,然後使用您當前的解決方案。 (b)而不是使用鍵,以XSLT 3.0映射的形式構建交叉文檔索引。事情是這樣的:

<xsl:mode name="index" on-no-match="shallow-skip"/> 

<xsl:variable name="globalIndex" as="map(xs:string, element(*))"> 
    <xsl:map> 
    <xsl:apply-templates mode="index"/> 
    </xsl:map> 
</xsl:variable> 

<xsl:template match="class" mode="index"> 
    <xsl:map-entry key="@name" select="."/> 
    <xsl:apply-templates mode="index"/> 
</xsl:template> 

<xsl:template match="import" mode="index"> 
    <xsl:apply-templates select="doc(@file)" mode="index"/> 
</xsl:template> 

,然後在那裏你以前使用key('parent', @base),你現在可以使用$globalIndex(@base)。 (c)除非你的處理器有一個聰明的優化器(比如Saxon-EE),它可以自動編制索引,這個解決方案不會給你鍵或映射的速度。但只使用XSLT 2.0:您先前使用key('parent', @base)

<xsl:variable name="allClasses" as="element(class)*"> 
    <xsl:apply-templates mode="index"/> 
</xsl:variable> 

<xsl:template match="class" mode="index"> 
    <xsl:sequence select="."/> 
    <xsl:apply-templates mode="index"/> 
</xsl:template> 

<xsl:template match="import" mode="index"> 
    <xsl:apply-templates select="doc(@file)" mode="index"/> 
</xsl:template> 

<xsl:template match="node()" mode="index"> 
    <xsl:apply-templates mode="index"/> 
</xsl:template> 

,然後,你現在可以使用$allClasses[@name=current()/@base]

+0

非常感謝您的及時回覆。沒有使用密鑰,可能實現這一目標?性能不是問題,因爲XML不是那麼大,因此使用非密鑰方法可能是可行的。如果不是,我會按照你建議的第一種方法。再次感謝您的時間。問候。 Hernan – hmb

+0

您可以使用類似的方法創建一個包含(引用)所有文檔中所有類元素的全局變量,然後使用過濾器表達式來查找包含具有所需名稱的類的類。 –

+0

您能否詳細說一下上述選項?據我所知,變量在應用模板模式之前被加載,並且它們的值不能被修改或更新。因此,我應該事先知道外部XML文件,但事實並非如此,因爲要查找的文件是XML本身的信息。什麼是我應該用來實現這個目標的最低XSL版本?我更喜歡使用1.0版本,但這不是必需的。 – hmb