XML-XSLT-使用第二个xml文档向xml文档添加新元素

时间:2018-07-10 10:48:38

标签: xml xslt saxon xslt-3.0

我已经遇到这个问题已有一段时间了,但无法解决,所以我决定在此处发布

我有以下简单的XML输入文档:

<?xml version="1.0" encoding="UTF-8"?>
<doc1 xmlns="http://www.eclipse.org/birt/2005/design" version="3.2.23">
    <text-prop name="docName">firstDoc</text-prop>
    <body>
        <column id="17"/>
        <column id="18"/>
        <column id="19"/>
    </body>
</doc1>

我想添加两个新元素,一个是<elements>,在其中要有<element>。然后,我还想添加一个<newColumn>元素的子元素<body>。所以我想得到的结果是:

<?xml version="1.0" encoding="UTF-8"?>
<doc1 xmlns="http://www.eclipse.org/birt/2005/design" version="3.2.23">
    <text-prop name="docName">firstDoc</text-prop>
   <elements>
      <element name="first element"/>
   </elements>
    <body>
        <column id="17"/>
        <column id="18"/>
        <column id="19"/>
      <newColumn name="dataSet">first element</newColumn>
    </body>
</doc1>

这是我正在使用的XSLT样式表,基于他在相关文章中给我的@Martin Honnen的样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xpath-default-namespace="http://www.eclipse.org/birt/2005/design"
    xmlns="http://www.eclipse.org/birt/2005/design"
    exclude-result-prefixes="xs"
    expand-text="yes"
    version="3.0">


  <xsl:param name="doc2" xmlns="">
<doc2>
    <elemList1>
        <elem1 ID="001" name="firstDoc" />
        <elem1 ID="002" name="secondDoc"/>
    </elemList1>
    <elemList2>
        <elem2 elemID="001">
                <elemData name="first element"/>
        </elem2>
        <elem2 elemID="002">
                <elemData name="second element"/>
        </elem2>
    </elemList2>
</doc2>      
  </xsl:param>

  <xsl:output indent="yes" cdata-section-elements="xml-prop"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:key name="layout-ref" match="elem1" use="@name" xpath-default-namespace=""/>
  <xsl:key name="report-ref" match="elem2" use="@elemID" xpath-default-namespace=""/>

  <xsl:template match="doc1/text-prop[@name = 'docName']">
      <xsl:next-match/>

      <xsl:variable name="layout" select="key('layout-ref', ., $doc2)"/>
      <xsl:variable name="report" select="key('report-ref', $layout/@ID, $doc2)"/>

      <elements>
          <xsl:apply-templates select="$report//elemData" xpath-default-namespace=""/>
      </elements>

  </xsl:template>

  <xsl:template match="elemData" xpath-default-namespace="">
      <element name="{@name}"/>
  </xsl:template>

  <!--HERE IT STOPS WORKING-->

  <xsl:template match="doc1/body/column[last()]" >
      <xsl:next-match/>
      <xsl:variable name="layout2" select="key('layout-ref', ., $doc2)"/>
      <xsl:variable name="report2" select="key('report-ref', $layout2/@ID, $doc2)"/>

      <newColumn name="dataSet">
          <xsl:value-of select="$report2/elemData/@name" xpath-default-namespace=""/>
      </newColumn>

  </xsl:template>


</xsl:stylesheet>

所以我实际上得到的结果就是这个:

<?xml version="1.0" encoding="UTF-8"?>
<doc1 xmlns="http://www.eclipse.org/birt/2005/design" version="3.2.23">
    <text-prop name="docName">firstDoc</text-prop>
   <elements>
      <element name="first element"/>
   </elements>
    <body>
        <column id="17"/>
        <column id="18"/>
        <column id="19"/>
      <newColumn name="dataSet"/>
    </body>
</doc1>

基本上,我希望元素<newColumn>的值与元素name的属性<element>的值相同,但是我无法访问该值并放入放在<newColumn> element

如您所见,我能够访问相同的值并将其作为新<element>元素的属性。

我不能以这种方式访问​​定义为<xsl:param>(doc2)的文档吗?

在以下位置查看XSLT字段: https://xsltfiddle.liberty-development.net/3NzcBtf/1

谢谢!

Alexandre Jacinto

1 个答案:

答案 0 :(得分:0)

似乎我在评论中对您想要的内容做出了正确的猜测,现在将其发布为答案,以便您可以将问题标记为已解决。

使用键功能时,您需要传递要查找的节点的键值,即在match="doc1/text-prop[@name = 'docName']"中传递key('layout-ref', ., $doc2),它是字符串值(例如firstDoc元素中的text-prop。在match="doc1/body/column[last()]"内,column元素没有该字符串值(您的列为空),因此从您的问题中还不清楚如何将列与其他元素相关联,除非您要导航到key('layout-ref', ancestor::doc1/text-prop[@name = 'docName'], $doc2)