XSLT

2011-05-29 13 views
2

で特定のXML文書を変換HIXSLT

私のXML文書には、次のレイアウトに

<root> 
    <child> 
    <item type="ID">id1</item> 
    <item type="TEXT">text1</item> 
    </child> 

    <child> 
    <item type="ID"/> 
    <item type="TEXT">text2</item> 
    </child> 

    <child> 
    <item type="ID"/> 
    <item type="TEXT">text3</item> 
    </child> 

    <child> 
    <item type="ID">id2</item> 
    <item type="TEXT">text4</item> 
    </child> 

    <child> 
    <item type="ID"/> 
    <item type="TEXT">text5</item> 
    </child> 

    ... 
</root> 

毎回を持っているタイプ= IDと空の項目タグが存在し、それが同じ値を有することを意味します前の兄弟。今、私はこれを私のソリューションは、

<?xml version="1.0"?> 

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="/"> 
    <root> 
     <xsl:apply-templates select="//child/item[@type='ID'][text()='id1' or text()='id2']"/> 
    </root> 
    </xsl:template> 

    <xsl:template match="child/item[text()='id1' or text()='id2']"> 
    <child id="{text()}"> 
     <xsl:value-of select="./../item[@type='TEXT']/."/> 
     <xsl:apply-templates select="./../following::*[1]/item[@type='ID'][not(text()='id1' or text()='id2')]"/> 
    </child> 
    </xsl:template> 

    <xsl:template match="child/item[not(text()='id1' or text()='id2')]"> 
    <xsl:value-of select="./../item[@type='TEXT']/."/> 
    <xsl:apply-templates select="./../following::*[1]/item[@type='ID'][not(text()='id1' or text()='id2')]"/> 
    </xsl:template> 

</xsl:stylesheet> 

それは動作しますが、醜いとunflexibleである

<root> 
    <child id="id1">text1text2text3</child> 
    <child id="id2">text4text5</child> 

    ... 
</root> 

にこれを変換したいです。たとえば、id1とid2だけでなく、任意のid値を持っていたらどうなりますか?誰か良いアドバイスかより良い解決策を持っていますか?

+0

XSLT 2を使用できますか、またはXSLT 1.0に制限されていますか? –

+0

良い質問、+1。キーを使用した、簡単で簡単なXSLT 1.0ソリューションについては、私の答えをご覧ください。 –

答えて

1

この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="/*"> 
     <root> 
      <!-- visit each "child" element with a non-blank ID --> 
      <xsl:for-each select="child[item[@type='ID'] != '']"> 
       <xsl:variable name="this-id" select="item[@type='ID']"></xsl:variable> 
       <child id="{$this-id}"> 
        <!-- visit this node and each following "child" element which 
         1. has a blank ID, and 
         2. whose immediate preceding non-blank ID child element is this one -->       
        <xsl:for-each select=".|following-sibling::child 
         [item[@type='ID'] = ''] 
         [preceding-sibling::child[item[@type='ID'] != ''][1]/item[@type='ID']=$this-id]"> 
         <xsl:value-of select="item[@type='TEXT']"/> 
        </xsl:for-each> 
       </child> 

      </xsl:for-each> 
     </root> 
    </xsl:template>  

</xsl:stylesheet> 

1

をXSLT 2.0溶液:

<xsl:template match="root"> 
    <xsl:for-each-group select="child" 
         group-starting-with="child[string(item[@type='ID'])]"> 
    <child id="{item[@type='ID']}"> 
     <xsl:value-of select="current-group()/item[@type='TEXT']" separator=""/> 
    </child> 
    </xsl:for-each-group> 
</xsl:template> 
1

このXSLT 1.0変換

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:key name="kFollowing" match="item[@type='TEXT']" 
     use="((..|../preceding-sibling::child) 
         /item[@type='ID'and string(.)] 
      )[last()]"/> 

<xsl:template match="/*"> 
    <root> 
    <xsl:apply-templates select= 
     "*[item[@type='ID' and string(.)]]"/> 
    </root> 
</xsl:template> 

<xsl:template match="*"> 
    <child id="{item[@type='ID']}"> 
    <xsl:copy-of select="key('kFollowing', item[@type='ID'])/text()"/> 
    </child> 
</xsl:template> 
</xsl:stylesheet> 

提供に適用される場合XML文書

<root> 
    <child id="id1">text1text2text3</child> 
    <child id="id2">text4text5</child> 
</root> 

説明@type='ID'とを有する第一の先行itemに一致するすべてのitem要素間の関係を表現するためにキーを使用し

<root> 
    <child> 
     <item type="ID">id1</item> 
     <item type="TEXT">text1</item> 
    </child> 
    <child> 
     <item type="ID"/> 
     <item type="TEXT">text2</item> 
    </child> 
    <child> 
     <item type="ID"/> 
     <item type="TEXT">text3</item> 
    </child> 
    <child> 
     <item type="ID">id2</item> 
     <item type="TEXT">text4</item> 
    </child> 
    <child> 
     <item type="ID"/> 
     <item type="TEXT">text5</item> 
    </child> ... 
</root> 

募集、正しい結果を生成子テキストノード。