合并和继承参数

Merging and inheriting parameters

使用 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 来保留顺序)并使用基于 'select'/'filtering' 的前同级名称 - 但是这个策略似乎不起作用,因为它们似乎不是真正的兄弟姐妹。这可以通过一个聪明的 group-by 来完成吗?完全可以做到吗? (我觉得可以)

我正在使用 xslt 版本 3.0 (saxon)

我认为您想要分组或合并,在 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 子元素确实是用字母表中排序的字母或单词命名。