XSLT adding elements on the same path
Consider the following XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>
<name>Bob</name>
<surname>Dylan</surname>
</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
</catalog>
I want to add e开发者_运维百科lements to this XML using XSLT, to get the following result:
<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>
<name>Bob</name>
<surname>Dylan</surname>
<!-- NEW -->
<middlename>???</middlename>
</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
<!-- NEW -->
<comment>great one</comment>
</cd>
<!-- NEW -->
<cd>
<title>Hide your heart</title>
<artist>
<name>Bonnie</name>
<surname>Tyler</surname>
</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</catalog>
To achieve that, I wrote the following XSLT:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="injectXml">
<xsl:param name="whatToInject"/>
<xsl:copy>
<xsl:copy-of select="node() | @*"/>
<xsl:copy-of select="$whatToInject"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//catalog">
<xsl:call-template name="injectXml">
<xsl:with-param name="whatToInject">
<cd>
<title>Hide your heart</title>
<artist>
<name>Bonnie</name>
<surname>Tyler</surname>
</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template match="//cd[year=1985]">
<xsl:call-template name="injectXml">
<xsl:with-param name="whatToInject">
<comment>great one</comment>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template match="//cd[year=1985]/artist">
<xsl:call-template name="injectXml">
<xsl:with-param name="whatToInject">
<middlename>???</middlename>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
Why it's not working? How to do it?
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my"
exclude-result-prefixes="my xsl"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:updates>
<update num="1">
<comment>great one</comment>
</update>
<update num="2">
<middlename>XXX</middlename>
</update>
<update num="3">
<cd>
<title>Hide your heart</title>
<artist>
<name>Bonnie</name>
<surname>Tyler</surname>
</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</update>
</my:updates>
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="catalog">
<xsl:call-template name="inject">
<xsl:with-param name="pUpdate" select="3"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="cd[year=1985]">
<xsl:call-template name="inject">
<xsl:with-param name="pUpdate" select="1"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="cd[year=1985]/artist">
<xsl:call-template name="inject">
<xsl:with-param name="pUpdate" select="2"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="inject">
<xsl:param name="pUpdate"/>
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
<xsl:apply-templates select=
"document('')/*/my:updates/*[@num=$pUpdate]/node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[ancestor::my:updates]">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:copy-of select=
"namespace::*[not(name()='my' or name()='xsl')]"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>
<name>Bob</name>
<surname>Dylan</surname>
</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
</catalog>
produces the wanted, correct result:
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>
<name>Bob</name>
<surname>Dylan</surname>
<middlename>XXX</middlename>
</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
<comment>great one</comment>
</cd>
<cd>
<title>Hide your heart</title>
<artist>
<name>Bonnie</name>
<surname>Tyler</surname>
</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</catalog>
Have you tried
match="//cd/year/[.='1985']"
精彩评论