合并和继承参数

时间:2018-10-19 13:21:42

标签: saxon xslt-grouping xslt-3.0

使用xslt 3.0版(撒克逊人版):

我有类似以下内容

<root>
  <template ID='1'>
    <params>
      <a>1</a>
      <b>1</b>
    </params>
  </template>

  <document1 templateID='1'>
    <params>
      <b>4</b>
      <c>5</c>
    </params>
  </document1>

</root>

基本上我需要转换成类似的东西

  <root>
    <document1 templateID='1'>
      <params>
        <a>1</a>
        <b>4</b>
        <c>5</c>
      </params>
    </document1>
  </root>

在示例中,参数a从模板继承,而参数b被文档本身覆盖,并且参数c在模板中未知或未设置。这类似于继承或CSS的工作方式。希望您能明白。在开始任务之前,我认为这应该不太困难(并且仍然希望我只是忽略某些东西)。

我尝试了以下方法:合并两个节点集(使用nodeset1 , nodeset2来保留顺序),并使用基于前一个同级名称的“选择” /“过滤”-但是这种策略似乎不起作用看来他们不是真正的兄弟姐妹。可以通过聪明的分组来完成吗?能做到吗? (我认为可以)

我正在使用xslt 3.0版(撒克逊人)

1 个答案:

答案 0 :(得分:1)

我认为您想分组或合并,在XSLT 3中合并将是

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output indent="yes"/>

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

  <xsl:key name="template-by-id" match="template" use="@ID"/>

  <xsl:template match="template"/>

  <xsl:template match="*[@templateID]/params">
      <xsl:copy>
          <xsl:merge>
              <xsl:merge-source name="template" select="key('template-by-id', ../@templateID)/params/*">
                  <xsl:merge-key select="string(node-name())"/>
              </xsl:merge-source>
              <xsl:merge-source name="doc" select="*">
                  <xsl:merge-key select="string(node-name())"/>
              </xsl:merge-source>
              <xsl:merge-action>
                  <xsl:copy-of select="(current-merge-group('doc'), current-merge-group('template'))[1]"/>
              </xsl:merge-action>
          </xsl:merge>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/jyH9rN8/

分组将会

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output indent="yes"/>

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

  <xsl:key name="template-by-id" match="template" use="@ID"/>

  <xsl:template match="template"/>

  <xsl:template match="*[@templateID]/params">
      <xsl:copy>
          <xsl:for-each-group select="key('template-by-id', ../@templateID)/params/*, *" group-by="node-name()">
              <xsl:copy-of select="head((current-group()[2], .))"/>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/jyH9rN8/1

我认为,由于xsl:merge要求输入必须在任何合并键上进行排序或首先对输入进行排序,因此,除非您的params子元素确实使用按字母排序的字母或单词。