xslt - XSLT在同一路径上添加元素

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


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

最佳答案

此转换:

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

关于xslt - XSLT在同一路径上添加元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2882963/

相关文章:

xml - 从不同的 XML 模式映射 XML 数据

在我的类路径中选择了 Java 的默认 JAXB 实现

xslt - 如何使用 XSLT 有条件地复制 XML 元素?

xslt - 循环不同的值

通过涉及特殊字符的 XSL 转换输出 HTML

xml - Firefox 和远程 XSL 样式表

java - 通过 XSLT 将外部文件内容作为 HTML 插入

XSLT:如果 Node = A 则设置 B=1 否则 B=2

xml - xsl - 最后一个 sibling

xslt - 如何使用 xslt 替换元素和属性中的命名空间前缀