2011-07-11 42 views
2

我在寻找,做以下的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> 

任何帮助将不胜感激。

谢谢。

回答

3

这是相当容易的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> 
+0

非常好,像一个魅力工作! – WayneH

+0

很高兴听到它。你有没有使用1.0或2.0版本? –