XSLT在同一路径上添加元素

时间:2010-05-21 14:31:53

标签: xslt

考虑以下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>

我想使用XSLT向此XML添加元素,以获得以下结果:

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

为实现这一目标,我编写了以下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>

为什么它不起作用?怎么做?

2 个答案:

答案 0 :(得分:1)

此转化

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

应用于提供的XML文档时:

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

生成想要的正确结果

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

答案 1 :(得分:0)

你试过吗

匹配= “//坎德拉/年/[.= '1985']”