我是XSLT转换的新手。我正在编写一些转换,以便重构在srcML中表达的代码,我正面临一个问题。我正在使用的XML输入如下所示:
....
<function><type><name>void</name></type> <name>DrawHorizontal</name>
<parameter_list>(
<param><decl><type><name>t_paper</name></type> <name>p</name></decl></param>,
<param><decl><type><name>int</name></type> <name>x</name></decl></param>,
<param><decl><type><name>int</name></type> <name>y</name></decl></param>)
</parameter_list>
<block>{.....
<expr_stmt><expr>
<name>
<name>p</name>
<index>[<expr><name>x</name></expr>]</index>
<index>[<expr><name>y</name></expr>]</index>
</name>.
<name>hor</name>
<operator>=</operator> 1
</expr>;</expr_stmt>
...
}</block>
</function>
我想要做的是,对于每个功能部分:
1)识别某种类型参数的名称(例如p类型为p_paper)
2)更改表达式语句,其中找到上一步中标识的参数()
输出应如下所示:
.....
<function><type><name>void</name></type> <name>DrawHorizontal</name>
<parameter_list>(
<param><decl><type><name>t_paper</name></type> <name>p</name></decl></param>,
<param><decl><type><name>int</name></type> <name>x</name></decl></param>,
<param><decl><type><name>int</name></type> <name>y</name></decl></param>)
</parameter_list>
<block>{.....
<expr_stmt><expr>
<name>p</name>.
<name>
<name>data</name>
<index>[<expr><name>x</name></expr>]</index>
<index>[<expr><name>y</name></expr>]</index>
</name>.
<name>hor</name>
<operator>=</operator> 1
</expr>;</expr_stmt>
...
}</block>
</function>
总之,我需要仅在找到特定类型的参数的地方转换expr_stmt节点(示例中为t_paper)。应该按原样复制文件的其余部分。
我的问题是我无法根据动态创建的条件(参数名称)将模板应用于特定部分。
一些不能正常工作的代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="//function">
<xsl:choose>
<xsl:when test="parameter_list/param/decl/type/name='t_paper'">
<xsl:copy>
<xsl:call-template name="transform-function" select="node()">
<xsl:with-param name="appearance" select="parameter_list/param/decl/name" />
</xsl:call-template>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<function><xsl:apply-templates select="node()"/></function>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="transform-function">
<xsl:param name="appearance" />
<xsl:if test="//expr_stmt/expr/name/name=$appearance">
substitution here
</xsl:if>
</xsl:template>
</xsl:stylesheet>
如果有人能给我一个提示,我将非常感激。
如果您需要更多详细信息,请告诉我,因为这是我在SO的第一个问题。
干杯,
d
答案 0 :(得分:1)
这个简单的转换(根本没有明确的条件):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kParamByNameType" match="param"
use="concat(decl/name, '+', decl/type/name)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"expr/name
[key('kParamByNameType',
concat(name, '+', 't_paper')
)
]">
<xsl:copy-of select="name"/>
<name>
<name>data</name>
<xsl:apply-templates select="name/following-sibling::node()"/>
</name>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<function>
<type>
<name>void</name>
</type>
<name>DrawHorizontal</name>
<parameter_list>(
<param>
<decl>
<type>
<name>t_paper</name>
</type>
<name>p</name>
</decl>
</param>,
<param>
<decl>
<type>
<name>int</name>
</type>
<name>x</name>
</decl>
</param>,
<param>
<decl>
<type>
<name>int</name>
</type>
<name>y</name>
</decl>
</param>)
</parameter_list>
<block>{.....
<expr_stmt>
<expr>
<name>
<name>p</name>
<index>[
<expr>
<name>x</name>
</expr>]
</index>
<index>[
<expr>
<name>y</name>
</expr>]
</index></name>.
<name>hor</name>
<operator>=</operator> 1
</expr>;
</expr_stmt> ... }
</block>
</function>
产生想要的结果:
<function>
<type>
<name>void</name>
</type>
<name>DrawHorizontal</name>
<parameter_list>(
<param>
<decl>
<type>
<name>t_paper</name>
</type>
<name>p</name>
</decl>
</param>,
<param>
<decl>
<type>
<name>int</name>
</type>
<name>x</name>
</decl>
</param>,
<param>
<decl>
<type>
<name>int</name>
</type>
<name>y</name>
</decl>
</param>)
</parameter_list>
<block>{.....
<expr_stmt>
<expr>
<name>p</name>
<name>
<name>data</name>
<index>[
<expr>
<name>x</name>
</expr>]
</index>
<index>[
<expr>
<name>y</name>
</expr>]
</index>
</name>.
<name>hor</name>
<operator>=</operator> 1
</expr>;
</expr_stmt> ... }
</block>
</function>
<强>解释强>:
仅针对所请求类型的参数覆盖identity rule。
使用key 方便地定义参数声明与其(名称,类型)之间的映射
答案 1 :(得分:0)
这是一个xsl:key元素/ key()函数回答
我不得不退出你的两步解决方案,找到一个可行的答案。我不知道你从哪里得到你的表达式语句,但我想这是来自C#/ .NET的东西。
在任何情况下,我都会看到你正在做的是包装一个类型,以便表达式改变:
p[x][y] to p.data[x][y]
如果是这种情况,我选择只在表达式的组件上匹配模板,而不是对整个函数应用不同的外观。然后有条件地在每个参数名称上,我查找类型以查看它是否是您正在寻找的那个。可以为要捕获的每种类型添加额外的“when”语句:
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<!-- key('parambyname','p')/type/name eq 't_paper' -->
<xsl:key name="parambyname" match="parameter_list/param/decl" use="name"/>
<xsl:template match="//expr_stmt/expr//name">
<xsl:choose>
<xsl:when test="key('parambyname',text())/type/name eq 't_paper'">
<xsl:copy>
<xsl:apply-templates select="./text()" />
</xsl:copy>
<xsl:text>.</xsl:text>
<name>data</name>
<xsl:apply-templates select="!text()"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>