开发者

XSLT adding elements on the same path

开发者 https://www.devze.com 2022-12-30 23:24 出处:网络
Consider the following XML: <?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <catalog> <cd>

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']"

0

精彩评论

暂无评论...
验证码 换一张
取 消