Próbowałem skopiować węzeł i zmienić jego atrybuty. Zasadniczo chcę <parent id="1">
mieć również <child id="3">
i dodaj do niego atrybut, w tym dokumencie:
<container>
<parent id="1">
<child id="1"/>
<child id="2"/>
</parent>
<parent id="2">
<child id="1"/>
<child id="2"/>
<child id="3" attrs="I am special"/>
</parent>
</container>
Powstały dokument wyglądałby następująco:
<container>
<parent id="1">
<child id="1"/>
<child id="2"/>
<child id="3" attrs="I am special" cloned="I have been cloned"/>
</parent>
<parent id="2">
<child id="1"/>
<child id="2"/>
<child id="3" attrs="I am special"/>
</parent>
</container>
Aby skopiować dziecko, po prostu zaznaczam plik parent
Chcę wypełnić i apply-templates
z przedmiotem jego pragnienia, podobnie:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>
<!-- copy everything verbatim -->
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="parent[@id="1"]/child[last()]">
<xsl:call-template name="identity"/>
<xsl:apply-templates select="//*/child[@id="3"]"/>
</xsl:template>
</xsl:stylesheet>
Po zadbaniu o kopię próbowałem zmienić atrybut, ale bezskutecznie. Nic nigdy nie jest dopasowywane, a atrybut nie jest dodawany z następującym szablonem:
<xsl:template match="child[@id="3" and ../@id="1"]">
<xsl:apply-templates select="@*|node()" />
<xsl:attribute name="clone">I have been cloned</xsl:attribute>
</xsl:template>
Przy moim ograniczonym zrozumieniu XSLT zostałoby to wyzwolone podczas apply-templates
, skopiowałoby węzły i dodał mój atrybut. Dane wyjściowe mówią inaczej: child id="3"
zostanie skopiowany, ale bez znaku atrybutu.
Myślałem, że być może nowo dodany węzełnie był jeszcze "t" dostępny "lub coś w tym stylu, ale prosta reguła będzie do niego pasować (to nie jest dobre, ponieważ modyfikuje oryginalny węzeł, z którego kopiuję):
<xsl:template match="child[@id="3"]">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
<xsl:attribute name="att1">I have been cloned?!</xsl:attribute>
</xsl:copy>
</xsl:template>
Myślałem, że mogłem zepsuć predykat, ale dodanie atrybutu z podobnym predykatem (bez poprzedniej kopii) działa jak urok:
<xsl:template match="child[@id="1" and ../@id="1"]">
<xsl:copy>
<xsl:attribute name="clone">Nope, just a normal kid</xsl:attribute>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
Pomyślałem też, że mój szablon „kopiowania” mógł mieć wyższy priorytet, ale granie z priorytetem też nie pomogło.
Czy czegoś brakuje?
Odpowiedzi:
1 dla odpowiedzi № 1Nowy element jest częścią drzewa wyników, nie można go dopasować w tym samym kroku transformacji. Sugerowałbym użycie trybu do zmiany przetwarzania elementu do dodania:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="@*|node()" mode="#all">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="parent[@id="1"]/child[last()]">
<xsl:next-match/>
<xsl:apply-templates select="//*/child[@id="3"]" mode="add-att"/>
</xsl:template>
<xsl:template match="child[@id="3"]" mode="add-att">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="att1">I have been cloned?!</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:transform>
Online w http://xsltransform.net/ncntCTd.