2013-02-08 2 views
-1

Может кто-нибудь помочь со следующим?Как превратить плоский массив xml в дерево?

Мне нужно преобразовать

<categories type="array"> 
     <category type="array"> 
     <category-name><![CDATA[Categories]]></category-name> 
     <category-name><![CDATA[BAGS & TRIPODS]]></category-name> 
     <category-name><![CDATA[Bags & Cases]]></category-name> 
     <category-name><![CDATA[soft cases]]></category-name> 
     <category-name><![CDATA[camera]]></category-name> 
     </category> 
    </categories> 

в

<Category> 
     <Name>BAGS &amp; TRIPODS</Name> 
     <Category> 
      <Name>Bags &amp; Cases</Name> 
      <Category> 
      <Name>soft cases</Name> 
      <Category> 
       <Name>camera</Name> 
      </Category> 
      </Category> 
     </Category> 
     </Category> 

Это должно быть в XSLT 1.0. Благодаря!

+0

Честно говоря, я посмотрел на некоторые примеров с генерацией ключей, но для меня это не имеет смысла. Кажется, что это невозможно без каких-либо родительских идентификаторов id/child id. – jstalnaker

+0

Странно, что пять человек проголосовали за то, чтобы закрыть этот вопрос как не подлежащий ответу, когда был предложен ответ, который ОП объявил полезным. Вопрос немного расплывчатый, но не безответственный. –

ответ

3

Вы имеете в виду, что хотите превратить плоскую последовательность в дерево, в котором каждый родитель имеет ровно один ребенок?

В шаблоне для родительского элемента, применяются шаблоны не для всех детей, но только первого ребенка:

<xsl:template match="category[@type='array']"> 
    <xsl:apply-templates select="*[1]"/>  
    </xsl:template> 

Затем в шаблоне для каждого из детей, справиться с этим ребенком, выписав новый Категория элемент и его имя, а затем применить шаблоны к сразу после собрата:

<xsl:template match="category-name"> 
    <Category> 
     <Name> 
     <xsl:apply-templates/> 
     </Name> 
     <xsl:apply-templates select="following-sibling::*[1]"/> 
    </Category> 
    </xsl:template> 

в вашем примере, начальный элемент массива, кажется, упали; нам понадобится специальный код для этого:

<xsl:template match="category-name 
         [normalize-space = 'Categories']"> 
    <xsl:apply-templates select="following-sibling::*[1]"/> 
    </xsl:template> 

Все вместе:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="category[@type='array']"> 
    <xsl:apply-templates select="*[1]"/>  
    </xsl:template> 

    <xsl:template match="category-name[normalize-space = 'Categories']"> 
    <xsl:apply-templates select="following-sibling::*[1]"/> 
    </xsl:template> 

    <xsl:template match="category-name"> 
    <Category> 
     <Name> 
     <xsl:apply-templates/> 
     </Name> 
     <xsl:apply-templates select="following-sibling::*[1]"/> 
    </Category> 
    </xsl:template> 

</xsl:stylesheet> 

От входа вы даете, это производит следующее:

<Category> 
    <Name>Categories</Name> 
    <Category> 
    <Name>BAGS &amp; TRIPODS</Name> 
    <Category> 
     <Name>Bags &amp; Cases</Name> 
     <Category> 
     <Name>soft cases</Name> 
     <Category> 
      <Name>camera</Name> 
     </Category> 
     </Category> 
    </Category> 
    </Category> 
</Category> 
+0

Нам нужно пропустить первый узел, в котором указаны категории в целом. Мне пришлось изменить первый шаблон на для этого работать. – jstalnaker

+0

Нет, вам не нужно вообще пропускать первый узел; вам просто нужно избегать производства продукции; это точка шаблона, который проверяет для normalize-space() = «Категории». Но начиная со второго ребенка тот же эффект, на вклад, который вы даете. –

Смежные вопросы