XSLT:如何在<;xsl:copy>;?

XSLT:如何在<;xsl:copy>;?,xslt,xslt-1.0,xslt-2.0,Xslt,Xslt 1.0,Xslt 2.0,我有一个XML文档,我想更改其中一个属性的值 首先,我使用以下方法将所有内容从输入复制到输出: <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> 现在我想更改名为“property”的任何元素中的属性“type”的值。您需要一个与目标属性匹

我有一个XML文档,我想更改其中一个属性的值

首先,我使用以下方法将所有内容从输入复制到输出:

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


现在我想更改名为
“property”
的任何元素中的属性
“type”
的值。您需要一个与目标属性匹配的模板,而不是其他

<xsl:template match='XPath/@myAttr'>
  <xsl:attribute name='myAttr'>This is the value</xsl:attribute>
</xsl:template>

这就是价值

这是对已有的“全部复制”的补充(在XSLT中,默认情况下始终存在)。有一个更具体的匹配项将优先使用。

通过一个简单的示例测试,效果很好:

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="@type[parent::property]">
  <xsl:attribute name="type">
    <xsl:value-of select="'your value here'"/>
  </xsl:attribute>
</xsl:template>

编辑以包含Tomalak的建议。

用于以下XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
    <property type="foo"/>
    <node id="1"/>
    <property type="bar">
        <sub-property/>
    </property>
</root>

我能够让它使用以下XSLT:

<?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="//property">
        <xsl:copy>
            <xsl:attribute name="type">
                <xsl:value-of select="@type"/>
                <xsl:text>-added</xsl:text>
            </xsl:attribute>
            <xsl:copy-of select="child::*"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

-增加

这个问题有一个经典的解决方案:使用和重写是最基本、最强大的XSLT设计模式之一:


应用于此XML文档时

<t>
  <property>value1</property>
  <property type="old">value2</property>
</t>
<t>
  <property>value1</property>
  <property type="myNewType">value2</property>
</t>

价值1
价值2
产生所需结果

<t>
  <property>value1</property>
  <property type="old">value2</property>
</t>
<t>
  <property>value1</property>
  <property type="myNewType">value2</property>
</t>

价值1
价值2

我有一个类似的例子,我想从一个简单的节点中删除一个属性,但不知道哪个轴可以让我读取属性名称。最后,我所要做的就是使用


@*[name(.)!='AttributeNameToDelete']

如果根元素中有xmlns定义,则前两个答案将不起作用:

<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
    <property type="old"/>
</html>

所有的解决方案都不适用于上述xml

可能的解决方案如下:

<?xml version="1.0"?> 

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:template match="node()[local-name()='property']/@*[local-name()='type']">
      <xsl:attribute name="{name()}" namespace="{namespace-uri()}">
                some new value here
          </xsl:attribute>
  </xsl:template>

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

这里有一些新的价值

如果源XML文档有自己的名称空间,则需要在样式表中声明名称空间,为其分配前缀,并在引用源XML元素时使用该前缀-例如:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml">

<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes" />

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

<!-- exception-->    
<xsl:template match="xhtml:property/@type">
    <xsl:attribute name="type">
        <xsl:text>some new value</xsl:text> 
    </xsl:attribute>
</xsl:template>

</xsl:stylesheet>

一些新的价值
或者,如果您愿意:

...
<!-- exception-->    
<xsl:template match="@type[parent::xhtml:property]">
  <xsl:attribute name="type">
        <xsl:text>some new value</xsl:text> 
  </xsl:attribute>
</xsl:template>
...
。。。
一些新的价值
...

增编: 在事先不知道XML名称空间的情况下,您可以执行以下操作:

<?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="utf-8" indent="yes" omit-xml-declaration="yes" />

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

<!-- exception -->
<xsl:template match="*[local-name()='property']/@type">
    <xsl:attribute name="type">
        <xsl:text>some new value</xsl:text> 
    </xsl:attribute>
</xsl:template>

一些新的价值


当然,很难想象这样一种场景:您事先知道源XML文档包含一个名为“property”的元素,其中一个名为“type”的属性需要替换,但仍然不知道文档的名称空间。我添加这一点主要是为了说明如何简化您自己的解决方案。

我也遇到了同样的问题,我解决了它,如下所示:

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

<!-- copy property element while only changing its type attribute -->
<xsl:template match="property">
  <xsl:copy>
    <xsl:attribute name="type">
      <xsl:value-of select="'your value here'"/>
    </xsl:attribute>
    <xsl:apply-templates select="@*[not(local-name()='type')]|node()"/>
  </xsl:copy>
</xsl:template>


另一个版本是,这也是我想在原始评论中说的,但忘了实际键入它。;-)@托马拉克:看情况。我更喜欢parent/@类型。但这显然是主观的。property/@type更好,因为它更清晰易懂。也许效率更高(几微秒:),但幸运的是,这种情况很少发生。考虑到OP从未指定有任何名称空间,所以描述一个不认为它们是“错误”的答案可能有点不仁慈。然而,为了其他利益相关方的利益,一个更“完整”的答案可能会包括一个“只有在没有名称空间的情况下才有效”的警告,但这绝对不是完全回答问题所必需的。我在没有“全部复制”部分的情况下尝试过,它只得到了标签之间的内容。没有复制任何标记本身或属性。+1,因为它的简单性,并且这将适用于所提供的用例,以及更复杂的xpath,在xpath中,您只想在非常特定的xpath处更改元素的属性(这是我在本页上寻找的).+1,因为如果要更改副本中的属性,此构造非常有用。但答案并不完整。看看这个答案,我的意思是:你使这比它需要的复杂得多。我已经发布了一个答案,展示了如何让前两个答案在你的情况下发挥作用。你的答案比我的复杂得多。我不明白你为什么在我发完帖子后给出额外的答案。你应该做的是加上我的答案。坦率地说,如果属性也有名称空间,那么您的答案是错误的。如果有名称空间定义,这个解决方案就不起作用。几天前我写了一篇评论,答案的作者回答说。但是现在它们已经不见了,所以我必须把这些评论转达给那些来到这里的人,不要被那些错误的答案误导,特别是那些倾向于误导的作家。也许你过于关注理论而不是问题本身。谷歌把我带到这里,你的回答很有帮助,但根本不能解决我的问题。所以我最终得到了一个更好的名称空间,不管它在理论上是对是错,或者可能会引起一些人对名称空间的狂热。我所关心的是找到一种方法来解决我的问题,我希望我的经验可以帮助其他有类似情况的人。你的回答真的很有帮助,在这里你真的是一个热情的回答者。但是我必须说,你为这个问题给出的解决方案根本不起作用。如果根元素上有名称空间定义,这个解决方案对我也不起作用。@dps你的问题与这个问题是正交的(无关的)。您的问题是关于XPath的最常见问题。只需搜索“XPath默认名称空间”,您可能会找到100个