2012-08-31 79 views
0

我想轉換表示樹的分層元素。這些數據提供了表格中的格式如下:使用XSLT進行遞歸轉換:表到樹

<?xml version="1.0" encoding="utf-16"?> 
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0"> 
    <asx:values> 
     <CONCEPTS> 
      <item> 
       <NO>1</NO> 
       <NS_PREFIX>de-gaap-ci</NS_PREFIX> 
       <XBRL_ID>bs.ass.monetary</XBRL_ID> 
       <IS_TUPLE>false</IS_TUPLE> 
       <FATHER_ID/> 
       <CONTEXT_REF>D-2012</CONTEXT_REF> 
       <UNIT_REF>EUR</UNIT_REF> 
       <DECIMALS>2</DECIMALS> 
       <PRECISION/> 
       <IS_NIL>false</IS_NIL> 
       <VALUE>12923.00-</VALUE> 
      </item> 
      <item> 
       <NO>2</NO> 
       <NS_PREFIX>de-gaap-ci</NS_PREFIX> 
       <XBRL_ID>bs.ass.string</XBRL_ID> 
       <IS_TUPLE>false</IS_TUPLE> 
       <FATHER_ID/> 
       <CONTEXT_REF>D-2012</CONTEXT_REF> 
       <UNIT_REF/> 
       <DECIMALS/> 
       <PRECISION/> 
       <IS_NIL>false</IS_NIL> 
       <VALUE>Test String</VALUE> 
      </item> 
      <item> 
       <NO>3</NO> 
       <NS_PREFIX>de-gaap-ci</NS_PREFIX> 
       <XBRL_ID>bs.ass.nil</XBRL_ID> 
       <IS_TUPLE>false</IS_TUPLE> 
       <FATHER_ID/> 
       <CONTEXT_REF>D-2012</CONTEXT_REF> 
       <UNIT_REF/> 
       <DECIMALS/> 
       <PRECISION/> 
       <IS_NIL>true</IS_NIL> 
       <VALUE/> 
      </item> 
      <item> 
       <NO>4</NO> 
       <NS_PREFIX>de-gaap-ci</NS_PREFIX> 
       <XBRL_ID>bs.ass.tuple1</XBRL_ID> 
       <IS_TUPLE>true</IS_TUPLE> 
       <FATHER_ID/> 
       <CONTEXT_REF>D-2012</CONTEXT_REF> 
       <UNIT_REF/> 
       <DECIMALS/> 
       <PRECISION/> 
       <IS_NIL>false</IS_NIL> 
       <VALUE/> 
      </item> 
      <item> 
       <NO>5</NO> 
       <NS_PREFIX>de-gaap-ci</NS_PREFIX> 
       <XBRL_ID>bs.ass.a</XBRL_ID> 
       <IS_TUPLE>false</IS_TUPLE> 
       <FATHER_ID>bs.ass.tuple1</FATHER_ID> 
       <CONTEXT_REF>D-2012</CONTEXT_REF> 
       <UNIT_REF/> 
       <DECIMALS/> 
       <PRECISION/> 
       <IS_NIL>false</IS_NIL> 
       <VALUE>Value for bs.ass.a</VALUE> 
      </item> 
      <item> 
       <NO>6</NO> 
       <NS_PREFIX>de-gaap-ci</NS_PREFIX> 
       <XBRL_ID>bs.ass.b</XBRL_ID> 
       <IS_TUPLE>false</IS_TUPLE> 
       <FATHER_ID>bs.ass.tuple1</FATHER_ID> 
       <CONTEXT_REF>D-2012</CONTEXT_REF> 
       <UNIT_REF/> 
       <DECIMALS/> 
       <PRECISION/> 
       <IS_NIL>false</IS_NIL> 
       <VALUE>Value for bs.ass.b</VALUE> 
      </item> 
     </CONCEPTS> 
     <CONTEXTS> 
      <item> 
       <ID>D-2012</ID> 
       <SCHEME>http://www.rzf-nrw.de/Steuernummer</SCHEME> 
       <IDENTIFIER>5117050051729</IDENTIFIER> 
       <IS_INSTANT>false</IS_INSTANT> 
       <DATE_A>2012-08-28</DATE_A> 
       <DATE_B>2012-08-30</DATE_B> 
      </item> 
      <item> 
       <ID>I-2012</ID> 
       <SCHEME>http://www.rzf-nrw.de/Steuernummer</SCHEME> 
       <IDENTIFIER>5117050051729</IDENTIFIER> 
       <IS_INSTANT>true</IS_INSTANT> 
       <DATE_A>2012-08-28</DATE_A> 
       <DATE_B/> 
      </item> 
     </CONTEXTS> 
     <UNITS> 
      <item> 
       <ID>EUR</ID> 
       <MEASURE_NS>iso4217</MEASURE_NS> 
       <MEASURE_VALUE>EUR</MEASURE_VALUE> 
      </item> 
         (...) 
     </UNITS> 
     <NAMESPACES> 
      <item> 
       <PREFIX>de-gcd</PREFIX> 
       <URI>http://www.xbrl.de/taxonomies/de-gcd-2011-09-14</URI> 
       <IS_DEFAULT>false</IS_DEFAULT> 
      </item> 
         (...) 
     </NAMESPACES> 
     <SCHEMAS> 
      <item> 
       <SCHEMA_REF>http://www.xbrl.de/taxonomies/de-gcd-2011-09-14.xsd</SCHEMA_REF> 
      </item> 
         (...) 
     </SCHEMAS> 
    </asx:values> 
</asx:abap> 

IS_TUPLE說,這種元素是樹中的一個父節點。在父親FATHER_ID內有這個父親的XBRL_ID的所有元素都應該是這個父親的孩子。因此,如果列FATHER_ID爲空,則該節點沒有父親。

我想用XSLT遞歸處理這些元素。目標格式是基本上是XML的XBRL。這裏是我的嘗試:

<xsl:template match="/"> 
<xbrl ...> 
    <xsl:apply-templates select="/CONCEPTS/item"> 
     <xsl:with-param name="rec_father_node" select="/" /> 
    </xsl:apply-templates> 
</xbrl> 
</xsl:template> 

<xsl:template name="tpl_concept" match="/CONCEPTS/item"> 

    <xsl:param name="rec_father_node"/> 

    <xsl:variable name="rec_father_id" select="string($rec_father_node/XBRL_ID/text())"/> 

    <xsl:variable name="father_id" select="string(*[local-name()='FATHER_ID'])"/> 
    <xsl:variable name="is_tuple" select="string(*[local-name()='IS_TUPLE'])"/>  
    <xsl:variable name="ns_prefix" select="string(*[local-name()='NS_PREFIX'])"/> 
    <xsl:variable name="xbrl_id" select="string(*[local-name()='XBRL_ID'])"/> 
    <xsl:variable name="name" select="$xbrl_id"/> 

    <xsl:if test="$is_tuple = 'false' and $rec_father_id = $father_id"> 

     <xsl:element name="{$name}"> 
         (...) 
     </xsl:element> 
    </xsl:if> 

    <xsl:if test="$is_tuple = 'true' and $rec_father_id = $father_id"> 
     <xsl:element name="{$name}"> 
      <xsl:choose> 
       <xsl:when test="$is_nil = 'true'"> 
        <xsl:attribute name="xsi:nil">true</xsl:attribute> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:apply-templates select="/CONCEPTS/item"> 
         <xsl:with-param name="rec_father_id" select="current()" /> 
        </xsl:apply-templates>     
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:element> 
    </xsl:if>  
</xsl:template> 

我的想法是以下幾點:節點是沒有父親有'列FATHER_ID裏面的字符串值。因此,我將根節點傳遞給參數rec_father_node以獲取此初始字符串。通過遞歸調用相同的模板,參數rec_father_node包含這個父親的節點,所以我可以讀出這位父親的XBRL_ID只添加在列FATHER_ID內具有此值的元素。

我的問題是:參數rec_father_node失去了遞歸調用傳遞的值。該值始終是初始<xsl:apply-templates .../>調用傳遞的根節點。

有沒有辦法將參數傳遞給遞歸模板調用?或者一般情況下,我怎樣才能將這個平面表格轉換爲嵌套元素的XML節點樹?

轉型的目標應該是這樣的(取名字從上面的例子,並增加了一些清晰度其他節點):任何幫助或意見

<?xml version="1.0" encoding="UTF-8"?> 
<xbrl> 
    <bs.ass.monetary>12923.00-</bs.ass.monetary> 
    <bs.ass.string>Test String</bs.ass.string> 
    <bs.ass.nil></bs.ass.nil> 
    <bs.ass.tuple1> 
     <bs.ass.a>Value for bs.ass.a</bs.ass.a> 
     <bs.ass.b>Value for bs.ass.b</bs.ass.b> 
    </bs.ass.tuple1> 
</xbrl> 

謝謝!

+1

雖然這是一件好事,讓您的輸入樣本儘可能的小,這也將有助於如果您的輸出樣本與輸入直接對應,則更多。謝謝! –

+0

好吧,我更新了要轉換爲原始源的源,並更新了所需的輸出。我評論你的答案。它基本上可以工作,但我仍然有問題。感謝您一直以來的幫助! –

+0

現在它已更新。由於某種原因,stackoverflow沒有保存我的更改! –

回答

2

你可以做的是首先定義一個關鍵字,根據它們的FATHER_ID元素來查找「子」項。

<xsl:key name="children" match="item" use="FATHER_ID" /> 

首先,雖然你會跟一個沒有父親的匹配項

<xsl:apply-templates select="item[FATHER_ID='']"/> 

然後,這是「元組」,你可以匹配他們,遞歸他們的孩子用鑰匙

匹配的項目開始
<xsl:template match="item[IS_TUPLE='true']"> 
    <xsl:element name="{XBRL_ID}"> 
     <xsl:apply-templates select="key('children', XBRL_ID)" /> 
    </xsl:element> 
</xsl:template> 

您還將擁有另一個item元素的模板,它將匹配非元組,它將輸出您喜歡的任何值即

試試下面的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:key name="children" match="item" use="FATHER_ID"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="//CONCEPTS"/> 
    </xsl:template> 

    <xsl:template match="CONCEPTS"> 
     <xbrl> 
     <xsl:apply-templates select="item[FATHER_ID='']"/> 
     </xbrl> 
    </xsl:template> 

    <xsl:template match="item[IS_TUPLE='true']"> 
     <xsl:element name="{XBRL_ID}"> 
     <xsl:apply-templates select="key('children', XBRL_ID)"/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="item"> 
     <xsl:element name="{XBRL_ID}"> 
     <xsl:value-of select="VALUE" /> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

當適用於您的樣品,您會收到以下

<xbrl> 
    <bs.ass.monetary>12923.00-</bs.ass.monetary> 
    <bs.ass.string>Test String</bs.ass.string> 
    <bs.ass.nil></bs.ass.nil> 
    <bs.ass.tuple1> 
     <bs.ass.a>Value for bs.ass.a</bs.ass.a> 
     <bs.ass.b>Value for bs.ass.b</bs.ass.b> 
    </bs.ass.tuple1> 
</xbrl>