首页 > 解决方案 > 基于数组元素,在 XSLT 1.0 中使用 for-each 时拆分为两个数组

问题描述

基于数组元素,在 XSLT 1.0 中使用 for-each 时拆分为两个数组。

<n1:request>
    <n1:metadata-criteria>
        <n1:metadata-criterion>
            <n1:name>id</n1:name>
            <n1:name-exists>true</n1:name-exists>
        </n1:metadata-criterion>
        <n1:metadata-criterion>
            <n1:name>direction</n1:name>
            <n1:value>A</n1:value>
        </n1:metadata-criterion>
        <n1:metadata-criterion>
            <n1:name>radius</n1:name>
            <n1:name-exists>true</n1:name-exists>
        </n1:metadata-criterion>
    </n1:metadata-criteria>
</n1:request>

在这里,我使用 for-each 作为元数据标准,我需要有条件地拆分为两个数组。第一个数组:如果存在,我需要创建为该元素的 [direction-A] 名称和值。第二个数组:如果存在名称,我需要创建该元素的 [id, radius] 名称。

我们只使用 XSLT 1.0。

<xsl:for-each select="./ns1:metadata-criterion">
            <xsl:if test="./ns1:value">
                <xsl:value-of select="./ns1:name" />
                <xsl:text>-</xsl:text>
                <xsl:value-of select="./ns1:value" />
                <xsl:choose>
                    <xsl:when test="position() != last()">
                        <xsl:text> AND </xsl:text>
                    </xsl:when>
                </xsl:choose>
            </xsl:if>
        </xsl:for-each>

标签: xmlxsltxslt-1.0

解决方案


使用以下输入 XML(我添加了命名空间声明n1

<n1:request xmlns:n1="http://ns1.com">
    <n1:metadata-criteria>
        <n1:metadata-criterion>
            <n1:name>id</n1:name>
            <n1:name-exists>true</n1:name-exists>
        </n1:metadata-criterion>
        <n1:metadata-criterion>
            <n1:name>direction</n1:name>
            <n1:value>A</n1:value>
        </n1:metadata-criterion>
        <n1:metadata-criterion>
            <n1:name>radius</n1:name>
            <n1:name-exists>true</n1:name-exists>
        </n1:metadata-criterion>
    </n1:metadata-criteria>
</n1:request>

和以下 XSLT-1.0 样式表(具有类似的命名空间声明ns1

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="http://ns1.com" version="1.0">
  <xsl:output method="xml" indent="no" omit-xml-declaration="yes" />
        
    <xsl:template match="/ns1:request/ns1:metadata-criteria">
        <xsl:copy>
            <array1>
                <xsl:for-each select="ns1:metadata-criterion[ns1:value]">
                    <xsl:value-of select="concat(ns1:name,'-',ns1:value)" />
                    <xsl:if test="position() != last()">
                        <xsl:text> AND </xsl:text>
                    </xsl:if>
                </xsl:for-each>
            </array1>
            <array2>
                <xsl:for-each select="ns1:metadata-criterion[ns1:name-exists]">
                    <xsl:value-of select="ns1:name" />
                    <xsl:if test="position() != last()">
                        <xsl:text> AND </xsl:text>
                    </xsl:if>
                </xsl:for-each>
            </array2>
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

你会得到这个输出:

<n1:metadata-criteria xmlns:n1="http://ns1.com">
    <array1>direction-A</array1>
    <array2>id AND radius</array2>
</n1:metadata-criteria>

请注意,命名空间是相同的,但它们的前缀不同(n1并且ns1对于相同的命名空间)。xsl:for-each检查给定元素是否存在的谓词。


推荐阅读