XSLT: Как изменить значение атрибута во время <xsl:copy>?

У меня есть XML-документ, и я хочу изменить значения для одного из атрибутов.

Сначала я скопировал все с входа для вывода использования:

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

И теперь я хочу изменить значение атрибута "type" в любом названном элементе "property".

56
задан Dimitre Novatchev 30 June 2019 в 20:31
поделиться

4 ответа

Протестированный на простом примере, хорошо работает:

<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.

36
ответ дан Welbog 26 November 2019 в 17:18
поделиться

Эта проблема имеет классическое решение : Используя и переопределение шаблон идентификационных данных является одним из самых фундаментальных и мощных шаблонов разработки 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>

При применении на этот XML-документ :

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

к требуемому результату приводят :

<t>
  <property>value1</property>
  <property type="myNewType">value2</property>
</t>
61
ответ дан Dimitre Novatchev 26 November 2019 в 17:18
поделиться

Вам нужен шаблон, который будет соответствовать Вашему целевому атрибуту и ничему иному.

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

Это - в дополнение к "копии все", Вы уже имеете (и на самом деле всегда присутствует по умолчанию в XSLT). При наличии более определенного соответствия это будет использоваться в предпочтении.

4
ответ дан Richard 26 November 2019 в 17:18
поделиться

Для следующего 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>
1
ответ дан Andrew Hare 26 November 2019 в 17:18
поделиться