2017-05-16 3 views
0

クラスとその基本クラスを表すXMLを、独自のメソッドと属性、さらにはすべての基本クラスのメソッドと属性を含むクラスで、OO継承が動作するように変換したいとします。 。外部データ内のXSL apply-template

そのためのXMLは以下のようになり

Michaelの助けを借りて

<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> 

に変換する必要があります

<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> 

、私はすべてのクラスが定義された場合は正常に動作し、次の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を処理するために次のパターンを追加しますキー

<?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: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は、以下のいずれかのようになります要素は外部ファイルで定義されたクラスに対して正常に動作しますが、基本クラスの継承動作はこれらのクラスには適用されません。

上記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ファイルはまた、私は2つの異なるアプローチを試してみました

インポート要素を含むことができることに注意してください。最初のものは、外部XMLファイルで宣言されたクラスを含むクラスのキーを使用することでした。これらの外部XMLファイルで定義されたクラスのキーを生成するために、私は外部ファイル名を事前に知らないので、失敗しました。2番目は「継承」モードの述語を適用することでしたが、そのファイルすべてに対して継承モードを持つテンプレートクラスを適用するために外部ファイル名がわからないため、もう一度失敗しました。

外部データからクラスの "継承"テンプレートを適用する方法に関するヘルプは、本当に感謝しています。どのようなアプローチでも、キーの有無にかかわらず、私にとっては大丈夫です。

ありがとうございます。

答えて

0

キーは1つのドキュメント内でのみ機能します。

(a)最初にすべてのドキュメントを1つにまとめてから、現在のソリューションを使用してください。

(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など)が自動的に索引付けされていない限り、このソリューションではキーやマップの速度が向上しません。

<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> 

、その後、あなたが以前にkey('parent', @base)を使用し、あなたが今$allClasses[@name=current()/@base]を使用することができますが、それは唯一のXSLT 2.0を使用しています。

+0

ご連絡いただきありがとうございます。キーを使用せずに、それを達成することは可能でしょうか? XMLはそれほど大きくないので、パフォーマンスは問題ではないので、非キーアプローチを使用することは実現可能です。そうでない場合、私はあなたが提案する最初のアプローチに従います。あなたの時間をもう一度ありがとう。よろしく。 Hernan – hmb

+0

同様のアプローチを使用して、すべてのドキュメントのすべてのクラス要素を含む(参照する)グローバル変数を作成し、フィルタ式を使用して、必要な名前のクラスを含むクラスを見つけることができます。 –

+0

上記のオプションについて少し詳しく教えてください。私が知る限り、変数はテンプレートパターンを適用する前にロードされ、その値は変更または更新できません。したがって、事前に外部XMLファイルを知っておく必要がありますが、探しているファイルはXMLそのものの情報なので、そうではありません。それを達成するために最低限必要なXSLバージョンは何でしょうか?私はバージョン1.0を使用することを好みますが、要件ではありません。 – hmb

関連する問題