2012-08-05 60 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模板