XSL:当属性Y为'A',B'或'F'时,如何更改属性X?

时间:2022-11-28 13:15:25

I'm working with a XML requests whereby I need to change the attribute value of an element if another attribute value is equal to one or more values. Xpath can't update the XML itself (so I understand) and I have been looking at XSL but it's quite complicated and I don't normally work in XML.

我正在处理XML请求,如果另一个属性值等于一个或多个值,我需要更改元素的属性值。 Xpath无法更新XML本身(所以我理解)并且我一直在研究XSL,但它非常复杂,我通常不使用XML。

This is a cut down version of the XML I'm working wth :

这是我正在使用的XML的缩减版本:

<t6:Catalogue xmlns:t6="http://xxx.yy.com">
    <t6:Items>
        <t6:Item />
        <t6:Item />
        <t6:Item />
    </t6:Items>
    <t6:Mappings>
        <t6:Mapping action="ADD_NEW" type="MAP"></t6:Mapping>
        <t6:Mapping action="ADD_NEW" type="FOO"></t6:Mapping>
        <t6:Mapping action="ADD_NEW" type="CAR"></t6:Mapping>
        <t6:Mapping action="ADD_NEW" type="PLANE"></t6:Mapping>
        <t6:Mapping action="ADD_NEW" type="MAP"></t6:Mapping>
    </t6:Mappings>
</t6:Catalogue>

I need to change the action from ADD_NEW to UPDATE_OLD in the Mappings block if type equals PLANE or CAR.

如果类型等于PLANE或CAR,我需要在Mappings块中将操作从ADD_NEW更改为UPDATE_OLD。

I have been looking at peoples' other examples of XSL and trying to wrap my head around how to start it but cannot. The tool I am using supports XSL and has a custom piece of software where I can drop an XSL template into it and it will apply it to the XML message I specify.

我一直在关注人们的XSL的其他例子,并试图围绕如何启动但不能。我正在使用的工具支持XSL,并且有一个自定义软件,我可以将XSL模板放入其中,并将它应用于我指定的XML消息。

But I'm not sure where to start -- at risk of sounding like, "Please do my work for me, SO users", if someone could give me at least a starting point of how I first point to my structure and then how to change a value IF x = y.

但我不知道从哪里开始 - 听起来有风险,“请为我做我的工作,SO用户”,如果有人能给我至少一个关于我如何首先指向我的结构的起点然后如何改变值IF x = y。

Thanks everyone.

2 个解决方案

#1


3  

The idea behind XSLT is to traverse the input XML tree and produce new output from the XML nodes.

XSLT背后的想法是遍历输入XML树并从XML节点生成新输出。

In its most fundamental form, this is done through template matching.

在最基本的形式中,这是通过模板匹配完成的。

  • write templates that match certain nodes based on a condition, and
  • 根据条件编写与某些节点匹配的模板,以及

  • write code that applies templates to nodes (related read).
  • 编写将模板应用于节点的代码(相关读取)。

The most basic template there is is the identity template.

最基本的模板是身份模板。

<xsl:template match="node() | @*">
  <xsl:copy>
    <xsl:apply-templates select="node() | @*" />
  </xsl:copy>
</xsl:template>

It is very unspecific; it can match any node and simply recursively calls itself, copying anything it finds. This produces an output document that is identical to the input, hence the name.

这是非常不明确的;它可以匹配任何节点,只需递归调用自身,复制它找到的任何东西。这会生成一个与输入相同的输出文档,因此也就是名称。

It gets more interesting when you add more specific templates, because XSLT will pick a better-matching template over a less specific one.

当您添加更多特定模板时,它会变得更有趣,因为XSLT将在不太具体的模板上选择更匹配的模板。

Like this one, which specifically only matches @action attributes that belong to an element that have @type PLANE or CAR. Instead of copying, it creates a new attribute node with the same name but a different value.

像这一个,它特别只匹配属于具有@type PLANE或CAR的元素的@action属性。它不是复制,而是创建一个具有相同名称但值不同的新属性节点。

<xsl:template match="@action[../@type = 'PLANE' or ../@type = 'CAR']">">
  <xsl:attribute name="action">ADD_OLD</xsl:attribute>
</xsl:template>

These two templates together achieve what you want. The generic one copies everything as-is, unless a more specific one matches a certain node.

这两个模板一起实现了你想要的。通用版本按原样复制所有内容,除非更具体的一个匹配某个节点。

#2


3  

If you only want to change this certain attribute you could go with an identity transform and manage @action with a template:

如果您只想更改此特定属性,则可以使用标识转换并使用模板管理@action:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t6="http://xxx.yy.com"
    exclude-result-prefixes="xs"
    version="2.0">

        <!-- Deleted template match="/" -->

        <xsl:template match="*|@*">
                <xsl:copy>
                        <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
        </xsl:template>

        <xsl:template match="@action[../@type = 'PLANE' or ../@type = 'CAR']">
                <xsl:attribute name="action" select="'ADD_OLD'"/>
        </xsl:template>
</xsl:stylesheet>

#1


3  

The idea behind XSLT is to traverse the input XML tree and produce new output from the XML nodes.

XSLT背后的想法是遍历输入XML树并从XML节点生成新输出。

In its most fundamental form, this is done through template matching.

在最基本的形式中,这是通过模板匹配完成的。

  • write templates that match certain nodes based on a condition, and
  • 根据条件编写与某些节点匹配的模板,以及

  • write code that applies templates to nodes (related read).
  • 编写将模板应用于节点的代码(相关读取)。

The most basic template there is is the identity template.

最基本的模板是身份模板。

<xsl:template match="node() | @*">
  <xsl:copy>
    <xsl:apply-templates select="node() | @*" />
  </xsl:copy>
</xsl:template>

It is very unspecific; it can match any node and simply recursively calls itself, copying anything it finds. This produces an output document that is identical to the input, hence the name.

这是非常不明确的;它可以匹配任何节点,只需递归调用自身,复制它找到的任何东西。这会生成一个与输入相同的输出文档,因此也就是名称。

It gets more interesting when you add more specific templates, because XSLT will pick a better-matching template over a less specific one.

当您添加更多特定模板时,它会变得更有趣,因为XSLT将在不太具体的模板上选择更匹配的模板。

Like this one, which specifically only matches @action attributes that belong to an element that have @type PLANE or CAR. Instead of copying, it creates a new attribute node with the same name but a different value.

像这一个,它特别只匹配属于具有@type PLANE或CAR的元素的@action属性。它不是复制,而是创建一个具有相同名称但值不同的新属性节点。

<xsl:template match="@action[../@type = 'PLANE' or ../@type = 'CAR']">">
  <xsl:attribute name="action">ADD_OLD</xsl:attribute>
</xsl:template>

These two templates together achieve what you want. The generic one copies everything as-is, unless a more specific one matches a certain node.

这两个模板一起实现了你想要的。通用版本按原样复制所有内容,除非更具体的一个匹配某个节点。

#2


3  

If you only want to change this certain attribute you could go with an identity transform and manage @action with a template:

如果您只想更改此特定属性,则可以使用标识转换并使用模板管理@action:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t6="http://xxx.yy.com"
    exclude-result-prefixes="xs"
    version="2.0">

        <!-- Deleted template match="/" -->

        <xsl:template match="*|@*">
                <xsl:copy>
                        <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
        </xsl:template>

        <xsl:template match="@action[../@type = 'PLANE' or ../@type = 'CAR']">
                <xsl:attribute name="action" select="'ADD_OLD'"/>
        </xsl:template>
</xsl:stylesheet>