xsl 在转换后递归应用模板
xsl apply-templates recursively after transformation
我在尝试递归应用模板时遇到问题。我想说的是,虽然我曾多次使用简单的 XSL 转换,但我对它们的了解并不深入。
我有以下 XML 表示具有方法和属性的 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>
并且我想获得一个 XML,其中包括 classes 以及所有属性和方法,无论是来自它本身还是来自它的基础 class,以相同的方式因为 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" >
<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>
我编写了以下 XSL,但仅适用于一级 class 继承。
<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>
当然,如果我应用上述转换的次数与 classes 具有的最大继承级别一样多,我(几乎)获得了所需的结果,但我的目标是将其放入只有一个转换。
任何指南将不胜感激。提前致谢。
以下是解决第一个问题的方法:
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>
应用于您的输入示例,结果将是:
<?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>
你的第二个问题我没看
我在尝试递归应用模板时遇到问题。我想说的是,虽然我曾多次使用简单的 XSL 转换,但我对它们的了解并不深入。
我有以下 XML 表示具有方法和属性的 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>
并且我想获得一个 XML,其中包括 classes 以及所有属性和方法,无论是来自它本身还是来自它的基础 class,以相同的方式因为 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" >
<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>
我编写了以下 XSL,但仅适用于一级 class 继承。
<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>
当然,如果我应用上述转换的次数与 classes 具有的最大继承级别一样多,我(几乎)获得了所需的结果,但我的目标是将其放入只有一个转换。
任何指南将不胜感激。提前致谢。
以下是解决第一个问题的方法:
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>
应用于您的输入示例,结果将是:
<?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>
你的第二个问题我没看