xsl:仅将模板应用于具有特定属性值的节点

发布于 2024-09-15 08:35:48 字数 1436 浏览 5 评论 0原文

我有一个 XML 文档,需要对其进行 XSLT 处理。结构类似于:

<root>
  <item value="1">
     <object/>
  </item>
  <item value="2" />
     <object/>
  </item>
</root>

我的目标是最终得到类似于以下内容的转换后的 XML:

<root>
 <parent>
  <object-one value-one="1"/>
 </parent>
 <parent>
  <object-two value-two="2"/>
 </parent>
</root>

我的 XSLT 类似于:

<xsl:apply-templates select="object" />


<xsl:template match="object">
    <xsl:call-template name="1" />
    <xsl:call-template name="2" />
</xsl:template>

<xsl:template name="1" match="object[item/@value = '1'">
  <xsl:element name="object-one" namespace="http://something.org">
    <xsl:attribute name="_Description">
      <xsl:value-of select="@_Type"/>
    </xsl:attribute>
    <xsl:attribute name="_Type">
      <xsl:value-of select="@_Amount"/>
   </xsl:attribute>
  </xsl:element>
</xsl:template>

 <xsl:template name="2" match="object[item/@value = '2'">
  <xsl:element name="object-two" namespace="http://something.org">
    <xsl:attribute name="OriginalAmount">
      <xsl:value-of select="@_Amount"/>
    </xsl:attribute>
  </xsl:element>
</xsl:template>

问题是所有项目节点都应用了相同的模板。如何将模板仅应用于特定节点?

I have an XML document which I'm subjected to an XSLT. The structure is similar to:

<root>
  <item value="1">
     <object/>
  </item>
  <item value="2" />
     <object/>
  </item>
</root>

My goal is to end up with a transformed XML similar to:

<root>
 <parent>
  <object-one value-one="1"/>
 </parent>
 <parent>
  <object-two value-two="2"/>
 </parent>
</root>

My XSLT is similar to:

<xsl:apply-templates select="object" />


<xsl:template match="object">
    <xsl:call-template name="1" />
    <xsl:call-template name="2" />
</xsl:template>

<xsl:template name="1" match="object[item/@value = '1'">
  <xsl:element name="object-one" namespace="http://something.org">
    <xsl:attribute name="_Description">
      <xsl:value-of select="@_Type"/>
    </xsl:attribute>
    <xsl:attribute name="_Type">
      <xsl:value-of select="@_Amount"/>
   </xsl:attribute>
  </xsl:element>
</xsl:template>

 <xsl:template name="2" match="object[item/@value = '2'">
  <xsl:element name="object-two" namespace="http://something.org">
    <xsl:attribute name="OriginalAmount">
      <xsl:value-of select="@_Amount"/>
    </xsl:attribute>
  </xsl:element>
</xsl:template>

The problem is the all item nodes are having the same template applied. How can I apply a template to only specific nodes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

岁月无声 2024-09-22 08:35:48

编辑:现在对于不同的输入示例(已更正为格式正确):

<root>
    <item value="1">
        <object/>
    </item>
    <item value="2" >
        <object/>
    </item>
</root>

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:num="number" extension-element-prefixes="num">
    <num:num>one</num:num>
    <num:num>two</num:num>
    <xsl:template match="root">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="item">
        <parent>
            <xsl:apply-templates/>
        </parent>
    </xsl:template>
    <xsl:template match="object">
        <xsl:variable name="vTextNumber" select="document('')/*/num:*[number(current()/../@value)]"/>
        <xsl:element name="object-{$vTextNumber}">
            <xsl:attribute name="value-{$vTextNumber}">
                <xsl:value-of select="../@value"/>
            </xsl:attribute>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

输出:

<root>
    <parent>
        <object-one value-one="1" />
    </parent>
    <parent>
        <object-two value-two="2" />
    </parent>
</root>

编辑2:现在,您的样式表片段中有什么问题?好吧,看来您不知道处理器如何解析模板规则应用以及 XPath 导航。

首先,此 object[item/@value = '1'] 将仅匹配此类输入

<object>
    <item value="1"/>
</object>

其次,考虑这三个规则

1 -

<xsl:template match="object">
</xsl:template> 

2 -

<xsl:template name="1" match="object[../@value = '1']"> 
</xsl:template> 

3 -

<xsl:template name="2" match="object[../@value = '2']"> 
</xsl:template> 

使用最后提供的输入,首先 object 元素(按文档顺序)将匹配规则 1 和 2,然后处理器将决定应用规则 2。为什么?来自http://www.w3.org/TR/xslt#conflict

接下来,所有匹配的模板规则
优先级低于匹配的优先级
模板规则或规则
最高优先级被排除
考虑。 a 的优先级
模板规则由
模板上的优先级属性
规则。这个值必须是真实的
数字(正数或负数),
将生产编号与
可选的前导减号 (-)。这
默认优先级计算如下
如下:

  • 如果模式包含多个由 | 分隔的替代项,则它
    等同于一组模板规则,每个规则一个
    替代方案。
  • 如果模式采用 QName 形式,前面带有 a
    ChildOrAttributeAxisSpecifier 或具有处理指令(Literal) 形式
    前面有 ChildOrAttributeAxisSpecifier,则优先级为 0。
  • 如果模式的形式为 NCName:*,前面带有 a
    ChildOrAttributeAxisSpecifier,则优先级为-0.25。
  • 否则,如果模式仅包含 NodeTest
    前面有 ChildOrAttributeAxisSpecifier,则优先级为 -0.5。
  • 否则,优先级为 0.5。

EDIT: Now for different input sample (corrected for well-formed):

<root>
    <item value="1">
        <object/>
    </item>
    <item value="2" >
        <object/>
    </item>
</root>

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:num="number" extension-element-prefixes="num">
    <num:num>one</num:num>
    <num:num>two</num:num>
    <xsl:template match="root">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="item">
        <parent>
            <xsl:apply-templates/>
        </parent>
    </xsl:template>
    <xsl:template match="object">
        <xsl:variable name="vTextNumber" select="document('')/*/num:*[number(current()/../@value)]"/>
        <xsl:element name="object-{$vTextNumber}">
            <xsl:attribute name="value-{$vTextNumber}">
                <xsl:value-of select="../@value"/>
            </xsl:attribute>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Output:

<root>
    <parent>
        <object-one value-one="1" />
    </parent>
    <parent>
        <object-two value-two="2" />
    </parent>
</root>

EDIT 2: Now, what is wrong within your stylesheet fragment? Well, it looks like you don't know how the processor resolves template rules applying, also XPath navegation.

First, this object[item/@value = '1'] will match only this kind of input

<object>
    <item value="1"/>
</object>

Second, consider this three rules

1 -

<xsl:template match="object">
</xsl:template> 

2 -

<xsl:template name="1" match="object[../@value = '1']"> 
</xsl:template> 

3 -

<xsl:template name="2" match="object[../@value = '2']"> 
</xsl:template> 

With your last provided input, first object element (in document order) will match rules 1 and 2, and then the processor would resolve to apply rule 2. Why? From http://www.w3.org/TR/xslt#conflict

Next, all matching template rules that
have lower priority than the matching
template rule or rules with the
highest priority are eliminated from
consideration. The priority of a
template rule is specified by the
priority attribute on the template
rule. The value of this must be a real
number (positive or negative),
matching the production Number with an
optional leading minus sign (-). The
default priority is computed as
follows:

  • If the pattern contains multiple alternatives separated by |, then it
    is treated equivalently to a set of template rules, one for each
    alternative.
  • If the pattern has the form of a QName preceded by a
    ChildOrAttributeAxisSpecifier or has the form processing-instruction(Literal)
    preceded by a ChildOrAttributeAxisSpecifier, then the priority is 0.
  • If the pattern has the form NCName:* preceded by a
    ChildOrAttributeAxisSpecifier, then the priority is -0.25.
  • Otherwise, if the pattern consists of just a NodeTest
    preceded by a ChildOrAttributeAxisSpecifier, then the priority is -0.5.
  • Otherwise, the priority is 0.5.
樱娆 2024-09-22 08:35:48

也许你可以让你的匹配更具体:

<xsl:template name="item1" match="item[@value=1]">
    <xsl:element name="item" namespace="http://something.org">
        <xsl:attribute name="_Description">
            <xsl:value-of select="@_Type"/>
        </xsl:attribute>
        <xsl:attribute name="_Type">
            <xsl:value-of select="@_Amount"/>
        </xsl:attribute>
    </xsl:element>
</xsl:template>

<xsl:template name="item2" match="item[@value=2]">
    <xsl:element name="item2_item" namespace="http://something.org">
        <xsl:attribute name="OriginalAmount">
            <xsl:value-of select="@_Amount"/>
        </xsl:attribute>
    </xsl:element>
</xsl:template>

Perhaps you can make your matches more specific:

<xsl:template name="item1" match="item[@value=1]">
    <xsl:element name="item" namespace="http://something.org">
        <xsl:attribute name="_Description">
            <xsl:value-of select="@_Type"/>
        </xsl:attribute>
        <xsl:attribute name="_Type">
            <xsl:value-of select="@_Amount"/>
        </xsl:attribute>
    </xsl:element>
</xsl:template>

<xsl:template name="item2" match="item[@value=2]">
    <xsl:element name="item2_item" namespace="http://something.org">
        <xsl:attribute name="OriginalAmount">
            <xsl:value-of select="@_Amount"/>
        </xsl:attribute>
    </xsl:element>
</xsl:template>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文