2015-02-09 91 views
-1

我有一個現有的xml文件,數據格式如下。代碼的前三個字母確定相同的組。XSLT扁平結構到地方

<Subjects> 
     <subject> 
     <code>ANT001000</code> 
      <literal>ANTIQUES/Americana</literal> 
     </subject> 
     <subject> 
      <code>ANT002000</code> 
      <literal>ANTIQUES/Art</literal> 
     </subject> 
     <subject> 
      <code>CKB100000</code> 
      <literal>COOKING/Beverages/General</literal> 
     </subject> 
     <subject> 
      <code>CKB006000</code> 
      <literal>COOKING/Beverages/Bartending</literal> 
     </subject> 
    </Subjects> 

我需要改變它看起來像這樣:

<node name="Antiques" id="1"> 
     <node name="Americana" id="2" /> 
     <node name="Art" id="3" /> 
    </node> 
<node name="Cooking" id="4"> 
     <node name="Beverages " id="6" /> 
      <node name="General" id="7" /> 
      <node name="Bartending" id="8" /> 
     </node> 
</node> 

我試了幾種方法,但不能得到它的工作。任何想法將不勝感激。

由於

+0

請至少顯示其中一種「多種方法」。謝謝! – 2015-02-09 18:43:19

+1

這不會很簡單。請指出是否使用XSLT 1.0或2.0。 - 代碼的其餘部分是否還有其他含義?(也許可以用來使其更容易)? – 2015-02-09 18:45:49

+0

http://stackoverflow.com/help/someone-answers – 2015-02-19 10:17:31

回答

1

我建議在幾次通過這樣做:

第一遍將標記化在每個subjectliteral元件列出的類別,並創建用於每一個category節點。在給定的例子中,這將導致:

<category path="">ANTIQUES</category> 
    <category path="ANTIQUES/">Americana</category> 
    <category path="">ANTIQUES</category> 
    <category path="ANTIQUES/">Art</category> 
    <category path="">COOKING</category> 
    <category path="COOKING/">Beverages</category> 
    <category path="COOKING/Beverages/">General</category> 
    <category path="">COOKING</category> 
    <category path="COOKING/">Beverages</category> 
    <category path="COOKING/Beverages/">Bartending</category> 

下一步將選擇所有頂部的類別(即,類別與空@path屬性):

<category path="">ANTIQUES</category> 
    <category path="">ANTIQUES</category> 
    <category path="">COOKING</category> 
    <category path="">COOKING</category> 

,減少該進一步只包括不同的值:

<category path="">ANTIQUES</category> 
    <category path="">COOKING</category> 

現在我們終於有一個像樣的起點,在這裏我們可以可以將模板應用到每個這樣的類別做:

<xsl:template match="category"> 
    <node name="{.}" id="{generate-id()}"> 
     <xsl:apply-templates select="$child-categories"/> 
    </node> 
</xsl:template> 

其中$child-categories代表其選擇屬性@path當前@path和電流值的串聯匹配的類別的表達式。

我正在使用每個類別的完整路徑,以防止在分類中分類名稱不唯一的情況下出現錯誤的肯定匹配。


作爲證明的概念,我已經寫了下面的樣式表,利用某些EXSLT擴展函數,即:exsl:節點集(),STR:記號化(),並設置:不同():

XSLT 1.0 + EXSLT

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common" 
xmlns:set="http://exslt.org/sets" 
xmlns:str="http://exslt.org/strings" 
extension-element-prefixes="exsl set str"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

<!-- first-pass --> 
<xsl:variable name="categories"> 
    <xsl:for-each select="/Subjects/subject"> 
     <xsl:variable name="steps" select="str:tokenize(literal, '/')" /> 
     <xsl:for-each select="$steps" > 
      <category> 
       <xsl:attribute name="path"> 
        <xsl:for-each select="preceding-sibling::token" > 
         <xsl:value-of select="concat(., '/')" /> 
        </xsl:for-each> 
       </xsl:attribute> 
       <xsl:value-of select="." /> 
      </category> 
     </xsl:for-each> 
    </xsl:for-each> 
</xsl:variable> 
<xsl:variable name="category-set" select="exsl:node-set($categories)/category" /> 

<xsl:template match="/"> 
    <!-- output--> 
    <nodes> 
     <xsl:apply-templates select="set:distinct($category-set[not(string(@path))])"/> 
    </nodes> 
</xsl:template> 

<xsl:template match="category"> 
    <node name="{.}" id="{generate-id()}"> 
     <xsl:apply-templates select="set:distinct($category-set[@path=concat(current()/@path, current(), '/')])"/> 
    </node> 
</xsl:template> 

</xsl:stylesheet> 

運行支持所有這些擴展函數(的libxslt)在處理器上時,結果是:

<?xml version="1.0" encoding="UTF-8"?> 
<nodes> 
    <node name="ANTIQUES" id="idp4576"> 
    <node name="Americana" id="idp4704"/> 
    <node name="Art" id="idp327680"/> 
    </node> 
    <node name="COOKING" id="idp25520"> 
    <node name="Beverages" id="idp25648"> 
     <node name="General" id="idp400976"/> 
     <node name="Bartending" id="idp27984"/> 
    </node> 
    </node> 
</nodes> 
+0

謝謝邁克爾。我只能使用XSLT 1.0,因此無法使用您的建議解決方案。然而,我遵循java中的代碼邏輯,它的工作就像一個魅力。謝謝 :) – user2118377 2015-02-23 22:24:07