XSLT:如何在<xsl:copy>期间更改属性值?

tom*_*ato 56 xslt xslt-2.0 xslt-1.0

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

首先,我使用以下方法复制从输入到输出的所

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

现在我想"type"在任何名为的元素中更改属性的值"property".

Dim*_*hev 61

这个问题有一个经典的解决方案:使用和压倒一切身份模板是最基本,最强大的XSLT设计模式之一:

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:param name="pNewType" select="'myNewType'"/>

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

    <xsl:template match="property/@type">
        <xsl:attribute name="type">
            <xsl:value-of select="$pNewType"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

应用于此XML文档时:

<t>
  <property>value1</property>
  <property type="old">value2</property>
</t>
Run Code Online (Sandbox Code Playgroud)

产生了想要的结果:

<t>
  <property>value1</property>
  <property type="myNewType">value2</property>
</t>
Run Code Online (Sandbox Code Playgroud)

  • @dps你的问题与这个问题正交(无关).而你的问题是关于XPath的最常见问题.只需搜索"XPath默认命名空间",您就可以找到数百个好的答案和解释. (2认同)

Wel*_*bog 36

测试一个简单的例子,工作正常:

<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>
Run Code Online (Sandbox Code Playgroud)

编辑包括Tomalak的建议.

  • property/@ type更好,因为它更清晰易懂.可能更高效(几微秒:)) (9认同)

ast*_*nia 7

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

<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
    <property type="old"/>
</html>
Run Code Online (Sandbox Code Playgroud)

所有解决方案都不适用于上述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>
Run Code Online (Sandbox Code Playgroud)


Ric*_*ard 5

您需要一个与您的目标属性匹配的模板,仅此而已。

<xsl:template match='XPath/@myAttr'>
  <xsl:attribute name='myAttr'>This is the value</xsl:attribute>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

这是对您已有的“全部复制”的补充(并且实际上在 XSLT 中默认始终存在)。有一个更具体的匹配,它将被优先使用。