xml - XSLT 复制所有节点,并按分隔符分割

标签 xml xslt

我正在寻找一个执行以下操作的 xslt:

以输入的xml为例:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <foo1>bar1</foo1>
    <foo2>bar2^bar3^bar4</foo2>
    <foo3>bar3^bar3</foo3>
    <unknown>more data</unknown>
</root>

我想将所有现有节点复制到生成的 xml 中。我不知道所有节点是什么,即我不知道我正在接收 foo1 节点,我只想直接复制它们。但对于某些节点,我确实知道它们是什么,并且我想用分隔符分隔它们并相应地对它们进行编号,如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <foo1>bar1</foo1>
    <foo2>
        <foo2-1>bar2</foo2-1>
        <foo2-2>bar3</food2-2>
        <foo2-3>bar4</foo2-3>
    </foo2>
    <foo3>
        <foo3-1>bar3</foo3-1>
        <foo3-2>bar3</food2-2>
    </foo3>
    <unknown>more data</unknown>
</root>

任何帮助将不胜感激。

谢谢。

最佳答案

这在 XSLT 2.0 中相当容易做到:

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

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

<xsl:template match="text()[contains(.,'^')]">  
    <xsl:variable name="elementName" select="name(..)"/>
    <xsl:for-each select="tokenize(.,'\^')">
         <xsl:element name="{$elementName}-{position()}">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:for-each>  
</xsl:template>

</xsl:stylesheet>

在 XSLT 1.0 中,您需要使用递归模板调用。例如:

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

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

<xsl:template match="text()[contains(.,'^')]">  
    <xsl:variable name="elementName" select="name(..)"/>

    <xsl:call-template name="splitIntoElements">
        <xsl:with-param name="baseName" select="name(..)" />
        <xsl:with-param name="txt" select="." />    
    </xsl:call-template>

</xsl:template>

<xsl:template name="splitIntoElements">
    <xsl:param name="baseName" />
    <xsl:param name="txt" />
    <xsl:param name="delimiter" select="'^'" />
    <xsl:param name="index" select="1" />

    <xsl:variable name="first" select="substring-before($txt, $delimiter)" />
    <xsl:variable name="remaining" select="substring-after($txt, $delimiter)" />

    <xsl:element name="{$baseName}-{$index}">
        <xsl:choose>
            <xsl:when test="$first">
                <xsl:value-of select="$first" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$txt" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:element>

    <xsl:if test="$remaining">
        <xsl:call-template name="splitIntoElements">
            <xsl:with-param name="baseName" select="$baseName" />
            <xsl:with-param name="txt" select="$remaining" />
            <xsl:with-param name="index" select="$index+1" />
            <xsl:with-param name="delimiter" select="$delimiter" />
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

关于xml - XSLT 复制所有节点,并按分隔符分割,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6657682/

相关文章:

xml - 撒克逊和 XPath。听不懂

php - 如何使用 SimpleXML 解析忽略错误的 XML

c# - 使用 Linq to XML 检索 xml 部分

c# - 撒克逊 XSLT : Serializer producing weird indents

xslt - 我如何使用 xsl :import with a variable in the path name?

xml - 什么是 : or n1: in this xslt stylesheet do?

java - 快速、轻量级的 XML 解析器

xml - 如何更新xslt中的变量值?

xml - 使用 xslt 从 XML 的多个属性值中获取单个值

java - 无法使用 `factory-method` 实例化单例