我想转换一个表示类及其基类的 XML,其中类包括它自己的方法和属性,以及它的所有基类的方法和属性,因为 OO 继承有效。
一个 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的帮助下,如果所有类都定义在同一个 XML 文件中,那么我有以下 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="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: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 文件中定义的类生成密钥。第二个是应用“继承”模式谓词,但我再次失败了,因为我不知道外部文件名,以便为所有文件应用具有继承模式的模板类。
任何有关如何从外部数据为类应用“继承”模板的帮助,将不胜感激。任何方法,有或没有钥匙,对我来说都很好。
提前致谢。