2016-01-16 1 views
1

У меня есть следующая плоская структура xml.XSLT 1.0 построить иерархию из отношений родитель-ребенок

<customUI > 
    <elements> 
    <tab id="1" parent="0"/> 
    <tab id="-1" parent="0"/> 
    <group id="-2" parent="-1"/> 
    <group id="2" parent="1"/> 
    <group id="11" parent="1"/> 
    <menu id="-27" parent="-26"/> 
    <menu id="-24" parent="-4"/> 
    <menu id="-18" parent="-4"/> 
    <menu id="-11" parent="-9"/> 
    <menu id="-10" parent="-9"/> 
    <menu id="-3" parent="-2"/> 
    <menu id="3" parent="2"/> 
    <menu id="10" parent="65"/> 
    <menu id="12" parent="11"/> 
    <menu id="16" parent="11"/> 
    <menu id="18" parent="11"/> 
    <menu id="25" parent="11" /> 
    <menu id="29" parent="11"/> 
    <menu id="46" parent="11"/> 
    <menu id="74" parent="-3"/> 
    <menu id="85" parent="11"/> 
    <menu id="89" parent="2"/> 
    <menu id="95" parent="2"/> 
    <menu id="104" parent="2"/> 
    <button id="-28" parent="-2"/> 
    <button id="-25" parent="-24"/> 
    <button id="-12" parent="-11"/> 
    <button id="32" parent="29"/> 
    <button id="26" parent="25"/> 
    <button id="41" parent="18"/> 
    <button id="66" parent="46"/> 
    <button id="82" parent="74"/> 
    <button id="86" parent="46"/> 
    <button id="87" parent="89"/> 
    <button id="90" parent="89"/> 
    <button id="99" parent="89"/> 
    <button id="58" parent="16"/> 
    <button id="42" parent="18"/> 
    <button id="47" parent="46"/> 
    <button id="48" parent="46"/> 
    <button id="33" parent="29"/> 
    <!-- The list continues --> 
    </elements> 
</customUI> 

То, что я хотел бы сделать, это построить иерархию, используя зависимость между значением «ид» и значение «родителя».

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

<xsl:template match="@*|node()" name="identity"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="tab"> 
    <xsl:variable name="controllerId" select="@id" as="xs:string"/> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <xsl:copy-of select="//*[@parent = $controllerId]"/> 
    </xsl:copy> 
</xsl:template> 


<xsl:template match="group" name="group"> 
    <xsl:variable name="controllerId" select="@id" as="xs:string"/> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <xsl:copy-of select="//*[@parent = $controllerId]"/> 
    </xsl:copy> 
</xsl:template> 


<xsl:template match="menu" name="menu"> 
    <xsl:variable name="controllerId" select="@id" as="xs:string"/> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <xsl:copy-of select="//*[@parent = $controllerId]"/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

Это то, что я пробовал до сих пор, но это не сработает.

Любая помощь будет принята с благодарностью.

+0

Можете ли вы показать вывод, который вы ожидаете в этом случае? Спасибо! –

ответ

1

Это немного грубо, но это должно работать:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <!-- Identity template --> 
    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="elements"> 
    <xsl:copy> 
     <xsl:for-each select="*"> 
     <xsl:if test="not(../*[@id=current()/@parent])"> 
      <xsl:apply-templates select="."/> 
     </xsl:if> 
     </xsl:for-each> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="elements/*"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
     <xsl:apply-templates select="../*[@parent = current()/@id]"/> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

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

Второй шаблон относится ко всему, что находится в шаблоне элементов, и копирует as-is, а также включает в себя любые другие элементы, родительский является текущим, рекурсивно.

Альтернативным с помощью клавиш, которые могут быть быстрее, но будет иметь проблемы, если есть более чем один элемент elements:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="elemsById" match="elements/*" use="@id"/> 
    <xsl:key name="elemsByParent" match="elements/*" use="@parent"/> 

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="elements"> 
    <xsl:copy> 
     <xsl:apply-templates select="*[not(key('elemsById',@parent))]"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="elements/*"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
     <xsl:apply-templates select="key('elemsByParent',@id)"/> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Я не в словах ... Как можно даже прийти с решением так быстро ... И самое удивительное кажется, что он работает. – Andy

+0

Удалось быть честным. В последнее время я сделал что-то очень похожее, это не было существенно иным. – Flynn1179

+0

Кстати, поскольку я начинаю, вы можете порекомендовать мне некоторые источники, откуда я могу узнать XSLT более структурированным способом, потому что сейчас я нахожусь на стадии, где больше проб и ошибок, и это, к сожалению, требует много времени. – Andy

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