每个 XSLT 2.0 参数 list/map

XSLT 2.0 paramer list/map with for each

这是我的 xslt 文件:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xpath-default-namespace="http://xmlns.jcp.org/xml/ns/persistence">

    <xsl:param name="childPath"/>
    <xsl:param name="childNode"/>

    <xsl:output method="xml" indent="yes"/>


    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[local-name()=$childNode]">
        <xsl:apply-templates select="document($childPath)//class"/>
    </xsl:template>
</xsl:stylesheet>

我的想法是我有一个父(模板)xml 文件和 N 个子 xml 文件。因此,我采用父级并为第一个子 xml 文件调用此 xslt 文件,为第二个子文件调用,依此类推。我使用 maven-xml-plugin 调用这个 xslt 文件,每次调用我都需要设置相当冗长的 transormationSet。

因此,我只想调用此 xslt 文件一次并将所有参数作为列表或地图传递。例如

$childNodes = nodeOne;nodeTwo;nodeThree
$childPaths = pathOne;pathTwo;pathTree

或点赞地图:

$children = nodeOne:pathOne;nodeTwo:pathTwo

谁能告诉我如何让我的 xslt 文件使用这样的 list/map 参数?

一种方法是引入模板模式并迭代名称/路径对

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xpath-default-namespace="http://xmlns.jcp.org/xml/ns/persistence">

    <xsl:param name="children" select="'name1:path1;name2:path2'"/>

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/">
        <xsl:variable name="here" select="."/>
        <xsl:for-each select="tokenize($children,';')">
            <xsl:apply-templates mode="child" select="$here">
                <xsl:with-param name="name" tunnel="true" select="tokenize(.,':')[1]"/>
                <xsl:with-param name="path" tunnel="true" select="tokenize(.,':')[2]"/>
            </xsl:apply-templates>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="*" mode="child">
        <xsl:param name="name" tunnel="true"/>
        <xsl:param name="path" tunnel="true"/>

        <xsl:if test="local-name()=$name">
            <xsl:apply-templates select="document($path)//class"/>
        </xsl:if>

        <xsl:apply-templates mode="child"/>
    </xsl:template>
</xsl:stylesheet>

使用 XPath 3.1/XSLT 3.0 地图,如 Saxon 9.8 及更高版本或 Saxon-JS 2 或 Altova XML 2017 R3 及更高版本所支持,您可以使用

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:map="http://www.w3.org/2005/xpath-functions/map"
  exclude-result-prefixes="#all"
  expand-text="yes">
  
  <xsl:param name="children" as="map(xs:string, xs:string)" select="map { 'nodeOne' : 'pathOne', 'nodeTwo' : 'pathTwo' }"/>

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

  <xsl:template match="*[local-name()=map:keys($children)]">
      <xsl:apply-templates select="document($children(local-name()))//class"/>
  </xsl:template>

</xsl:stylesheet>

作为坚持使用包含以分号分隔的值列表的字符串值的替代方法:

  <xsl:param name="childNodes">nodeOne;nodeTwo;nodeThree</xsl:param>
  
  <xsl:param name="childPaths">pathOne;pathTwo;pathTree</xsl:param>

  <xsl:variable name="childNodesSeq" select="tokenize($childNodes, ';')"/>
  
  <xsl:variable name="childPathsSeq" select="tokenize($childPaths, ';')"/>
  
  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="*[local-name()=$childNodesSeq]">
      <xsl:apply-templates select="document($childPathsSeq[index-of($childNodesSeq, local-name(current()))])//class"/>
  </xsl:template>