2015-02-09 93 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