首页 > 解决方案 > 使用 xsl 1.0 重复 n 次 xml 节点

问题描述

大家好我有以下xml:

<?xml version='1.0' encoding='UTF-8'?>
<service>
  <metadata>
        <collection>
                <metadata_id>id</metadata_id>
                <metadata_uuid>uuid</metadata_uuid>
        </collection>
  </metadata>
</service>

我想重复n次节点 <collection>...</collection> 以获得以下输出(每个节点中的id和uuid总是不同的)

<?xml version='1.0' encoding='UTF-8'?>
<service>
  <metadata>
        <collection>
                <metadata_id>id</metadata_id>
                <metadata_uuid>uuid</metadata_uuid>
        </collection>
        <collection>
                <metadata_id>id</metadata_id>
                <metadata_uuid>uuid</metadata_uuid>
        </collection>
        <collection>
                <metadata_id>id</metadata_id>
                <metadata_uuid>uuid</metadata_uuid>
        </collection>
        <collection>
                <metadata_id>id</metadata_id>
                <metadata_uuid>uuid</metadata_uuid>
        </collection>
.... (n time)

  </metadata>
</service>

我正在尝试使用身份转换:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <xsl:strip-space elements="*"/>

      <xsl:template match="service">
    <xsl:copy>
      <xsl:apply-templates select="metadata"/>
    </xsl:copy>
  </xsl:template>

  <!-- Select Particular Elements -->   
  <xsl:template match="metadata">
      <xsl:copy-of select="."/>
  </xsl:template>

</xsl:stylesheet>

但我不确定如何重复节点以获得所需的输出。有什么建议么?

标签: xmlxslt

解决方案


使用带参数的递归:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:param name="max">4</xsl:param>

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

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

  <xsl:template match="metadata">
      <xsl:copy>
          <xsl:apply-templates/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="collection">
      <xsl:param name="n" select="1"/>
      <xsl:copy>
          <xsl:apply-templates>
              <xsl:with-param name="n" select="$n"/>
          </xsl:apply-templates>
      </xsl:copy>
      <xsl:if test="$n &lt; $max">
          <xsl:apply-templates select=".">
              <xsl:with-param name="n" select="$n + 1"/>
          </xsl:apply-templates>
      </xsl:if>
  </xsl:template>

  <xsl:template match="collection/*">
      <xsl:param name="n"/>
      <xsl:copy>
          <xsl:value-of select="concat(., ' ', $n)"/>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

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

请注意,在带有 (1 到 4) 的 XSLT 2 中,您可以使用xsl:for-eachor 在 XSLT 3 中使用xsl:iterateor直接构造要处理的序列fold-left


推荐阅读