Я хочу добавить новый атрибут для каждого узла, кроме корневого.
Я считаю, что единственным элементом, в который вы хотите не добавить атрибут, является элемент документа (сверху). Это происходит в в этом документе XML, но в другом документе может быть другое имя, например topnode
, и вы хотите, чтобы решение работало и в этом случае.
Кроме того, если у вас есть элемент с именем rootnode
, который не является верхним элементом, вы, вероятно, хотите добавить новый атрибут к этому элементу.
Таким образом, следующее преобразование будет делать это, независимо от названия документа элемента:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*/*">
<xsl:copy>
<xsl:attribute name="newattribute">NEW</xsl:attribute>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
замечают шаблон спички наиважнейшей шаблона:
<xsl:template match="*/*">
Это соответствует каждому элементу, родительский узел которого также является элементом - эффективно исключая элемент top (document).
Когда преобразование применяется на поставленном XML документа:
<rootnode>
<section id="1" >
<outer param="p1">
<inner />
<inner />
</outer>
<outer param="p1">
<inner />
</outer>
<outer />
<outer param="p5"/>
</section>
<section id="2" >
<outer >
<inner anotherparam="ap1"/>
<inner param="p4"/>
<inner />
</outer>
</section>
</rootnode>
разыскиваемый, правильный результат получается:
<rootnode>
<section newattribute="NEW" id="1">
<outer newattribute="NEW" param="p1">
<inner newattribute="NEW"/>
<inner newattribute="NEW"/>
</outer>
<outer newattribute="NEW" param="p1">
<inner newattribute="NEW"/>
</outer>
<outer newattribute="NEW"/>
<outer newattribute="NEW" param="p5"/>
</section>
<section newattribute="NEW" id="2">
<outer newattribute="NEW">
<inner newattribute="NEW" anotherparam="ap1"/>
<inner newattribute="NEW" param="p4"/>
<inner newattribute="NEW"/>
</outer>
</section>
</rootnode>
Когда преобразование - без каких-либо изменений - применяется к аналогичному документу (только элемент документа переименован в topnode
):
<topnode>
<section id="1" >
<outer param="p1">
<inner />
<inner />
</outer>
<outer param="p1">
<inner />
</outer>
<outer />
<outer param="p5"/>
</section>
<section id="2" >
<outer >
<inner anotherparam="ap1"/>
<inner param="p4"/>
<inner />
</outer>
</section>
</topnode>
снова правильный результат получается:
<topnode>
<section newattribute="NEW" id="1">
<outer newattribute="NEW" param="p1">
<inner newattribute="NEW"/>
<inner newattribute="NEW"/>
</outer>
<outer newattribute="NEW" param="p1">
<inner newattribute="NEW"/>
</outer>
<outer newattribute="NEW"/>
<outer newattribute="NEW" param="p5"/>
</section>
<section newattribute="NEW" id="2">
<outer newattribute="NEW">
<inner newattribute="NEW" anotherparam="ap1"/>
<inner newattribute="NEW" param="p4"/>
<inner newattribute="NEW"/>
</outer>
</section>
</topnode>
И в случае, имеющего этот источник XML-документ (а <rootnode>
элемент был добавлен, что это не верхний элемент):
<rootnode>
<section id="1" >
<outer param="p1">
<inner />
<inner />
</outer>
<outer param="p1">
<inner />
</outer>
<outer />
<outer param="p5"/>
</section>
<rootnode/>
<section id="2" >
<outer >
<inner anotherparam="ap1"/>
<inner param="p4"/>
<inner />
</outer>
</section>
</rootnode>
Снова правильный результат получается тем же без изменений преобразование:
<rootnode>
<section newattribute="NEW" id="1">
<outer newattribute="NEW" param="p1">
<inner newattribute="NEW"/>
<inner newattribute="NEW"/>
</outer>
<outer newattribute="NEW" param="p1">
<inner newattribute="NEW"/>
</outer>
<outer newattribute="NEW"/>
<outer newattribute="NEW" param="p5"/>
</section>
<rootnode newattribute="NEW"/>
<section newattribute="NEW" id="2">
<outer newattribute="NEW">
<inner newattribute="NEW" anotherparam="ap1"/>
<inner newattribute="NEW" param="p4"/>
<inner newattribute="NEW"/>
</outer>
</section>
</rootnode>
урок:
Указание точного совпадения шаблонов может сэкономить много работы!
Было бы лучше сделать последнее правило шаблона match = "*", поскольку вы полагаетесь на него, сопоставляя элементы, предпочитая первое правило. –
@MichaelKay Я сделал редактирование - это то, что вы имеете в виду? –
Да, это безопаснее (не всегда можно полагаться на последнее правило, которое выбирается при совпадении двух правил, но «*» имеет более высокий приоритет, чем «node()», так что все в порядке.) –