2012-08-05 55 views
4

我需要一个XSLT 1.0,它可以分隔分隔符上的XML节点并创建单个节点。 例如,如果分隔符是“_”和XML是:XSLT - 使用分隔符分解节点

<root> 
    <a_b_c>hello<a_b_c> 
    <a_b_c1>world</a_b_c1> 
</root> 

结果XML应该是:不包含定界符

<root> 
    <a> 
     <b> 
      <c>hello</c> 
      <c1>world</c1> 
     </b> 
    </a> 
</root> 

节点,是应被输出。 我真的需要这个在XSLT1.0中 谢谢你的帮助。

回答

2

该转化

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

    <xsl:key name="kSameNameAdj" match="*" 
    use="concat(generate-id(..), 
       '+', 
       generate-id(preceding-sibling::*[not(name()=name(current()))][1]) 
      )"/> 

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

<xsl:template match="/"> 
    <xsl:variable name="vrtfPass1"> 
    <xsl:apply-templates select="node()"/> 
    </xsl:variable> 

    <xsl:apply-templates select="ext:node-set($vrtfPass1)" mode="compress"/> 
</xsl:template> 

<xsl:template name="explode" match= 
    "*[contains(name(),'_') 
    and not(substring(name(),1,1)='_') 
    and not(substring(name(), string-length(name()))='_') 
    ]"> 
    <xsl:param name="pName" select="name()"/> 
    <xsl:param name="pText" select="text()"/> 

    <xsl:choose> 
    <xsl:when test="not($pName)"> 
    <xsl:value-of select="$pText"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:element name="{substring-before(concat($pName, '_'), '_')}"> 
     <xsl:call-template name="explode"> 
     <xsl:with-param name="pName" select="substring-after($pName, '_')"/> 
     <xsl:with-param name="pText" select="$pText"/> 
     </xsl:call-template> 
     </xsl:element> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

    <xsl:template match="/" name="fold" mode="compress"> 
    <xsl:param name="pDoc" select="/"/> 

    <xsl:choose> 
    <xsl:when test="not($pDoc//*[name()=name(following-sibling::*[1])])"> 
     <xsl:copy-of select="$pDoc"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:variable name="vrtfThisPass"> 
     <xsl:apply-templates select="$pDoc/*" mode="compress"/> 
     </xsl:variable> 

     <xsl:call-template name="fold"> 
     <xsl:with-param name="pDoc" select="ext:node-set($vrtfThisPass)"/> 
     </xsl:call-template> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

<xsl:template match="node()|@*" mode="compress"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()[1]" mode="compress"/> 
    </xsl:copy> 
    <xsl:apply-templates select="following-sibling::node()[1]" mode="compress"/> 
</xsl:template> 

<xsl:template match="*[name()=name(following-sibling::*[1])]" mode="compress"> 
    <xsl:element name="{name()}"> 
    <xsl:apply-templates mode="compress" select= 
    "key('kSameNameAdj', 
      concat(generate-id(..), 
       '+',generate-id(preceding-sibling::*) 
       ) 
     )/node()"/> 
    </xsl:element> 
    <xsl:apply-templates mode="compress" select= 
    "key('kSameNameAdj', 
      concat(generate-id(..), 
       '+',generate-id(preceding-sibling::*) 
       ) 
     ) 
      [last()]/following-sibling::node()[1] 
    "/> 
</xsl:template> 
</xsl:stylesheet> 

当在下面的XML文档施加(提供的一个,延伸至更有挑战性):

<root> 
    <x>This is:</x> 
    <a_b_c>hello</a_b_c> 
    <a_b_c_d>my</a_b_c_d> 
    <a_b_c1>wonderful</a_b_c1> 
    <a_b_c>world</a_b_c> 
    <a_b>!</a_b> 
    <y>The End</y> 
</root> 

产生想要的,正确结果

<root> 
    <x>This is:</x> 
    <a> 
     <b> 
     <c>hello<d>my</d> 
     </c> 
     <c1>wonderful</c1> 
     <c>world</c>!</b> 
    </a> 
    <y>The End</y> 
</root> 

说明

0.1。 这是一个多通道转换。 第一遍将XML文档转换为:

<root> 
    <x>This is:</x> 
    <a> 
     <b> 
     <c>hello</c> 
     </b> 
    </a> 
    <a> 
     <b> 
     <c> 
      <d>my</d> 
     </c> 
     </b> 
    </a> 
    <a> 
     <b> 
     <c1>wonderful</c1> 
     </b> 
    </a> 
    <a> 
     <b> 
     <c>world</c> 
     </b> 
    </a> 
    <a> 
     <b>!</b> 
    </a> 
    <y>The End</y> 
</root> 

.2。 随后的过程,每个过程都将具有相同名称的任何相邻元素组压缩为具有该名称的单个元素 - 然后递归处理结果,直到不再有任何一组多于一个的相邻兄弟元素具有相同的名称。

.3。 第一次使用identity rule

.4。 接下来的通行证在“压缩”模式下使用fine-grade identity模板