Поиск определенного узла в файле XML

У меня есть XML с 5 или 6 уровнями. Все узлы имеют уникальный идентификатор. По этому идентификатору мне нужно найти указанный узел и создать список, показывающий только предков этого узла. Я попытаюсь объяснить лучше с кодами:

Это мой XML со всеми параметрами:

<MenuConfig>
<Menu name="name-1" location="location 1" title="Menu 1">
    <Item name="name-1.1" location="location 1.1.jsp" title="Menu 1.1"/>
    <Item name="name-1.2" location="location 1.2.jsp" title="Menu 1.2"/>
    <Item name="name-1.3" location="location 1.3.jsp" title="Menu 1.3">
        <Item name="name-1.3.1" location="location 1.3.1.jsp" title="Menu 1.3.1"/>
        <Item name="name-1.3.2" location="location 1.3.2.jsp" title="Menu 1.3.2"/>
    </Item>
    <Item name="name-1.4" location="location 1.4.jsp" title="Menu 1.3">
        <Item name="name-1.4.1" location="location 1.4.1.jsp" title="Menu 1.4.1"/>
        <Item name="name-1.4.2" location="location 1.4.2.jsp" title="Menu 1.4.2"/>
    </Item>
</Menu>
<Menu name="name-2" location="location 2" title="Menu 2">
    <Item name="name-2.1" location="location 2.1.jsp" title="Menu 2.1"/>
    <Item name="name-2.2" location="location 2.2.jsp" title="Menu 2.2"/>
    <Item name="name-2.3" location="location 2.3.jsp" title="Menu 2.3">
        <Item name="name-2.3.1" location="location 2.3.1.jsp" title="Menu 2.3.1"/>
        <Item name="name-2.3.2" location="location 2.3.2.jsp" title="Menu 2.3.2"/>
    </Item>
    <Item name="name-2.4" location="location 2.4.jsp" title="Menu 2.3">
        <Item name="name-2.4.1" location="location 2.4.1.jsp" title="Menu 2.4.1"/>
        <Item name="name-2.4.2" location="location 2.4.2.jsp" title="Menu 2.4.2"/>
    </Item>
</Menu>
<Menu name="name-3" location="location 3" title="Menu 3">
    <Item name="name-3.1" location="location 3.1.jsp" title="Menu 3.1"/>
    <Item name="name-3.2" location="location 3.2.jsp" title="Menu 3.2"/>
    <Item name="name-3.3" location="location 3.3.jsp" title="Menu 3.3">
        <Item name="name-3.3.1" location="location 3.3.1.jsp" title="Menu 3.3.1"/>
        <Item name="name-3.3.2" location="location 3.3.2.jsp" title="Menu 3.3.2"/>
    </Item>
    <Item name="name-3.4" location="location 3.4.jsp" title="Menu 3.3">
        <Item name="name-3.4.1" location="location 3.4.1.jsp" title="Menu 3.4.1">
            <Item name="name-3.4.1.1" location="location 3.4.1.1.jsp" title="Menu 3.4.1.1"/>
            <Item name="name-3.4.1.2" location="location 3.4.1.2.jsp" title="Menu 3.4.1.2"/>
        </Item>
        <Item name="name-3.4.2" location="location 3.4.2.jsp" title="Menu 3.4.2">
            <Item name="name-3.4.2.1" location="location 3.4.2.1.jsp" title="Menu 3.4.2.1"/>
            <Item name="name-3.4.2.2" location="location 3.4.2.2.jsp" title="Menu 3.4.2.2"/>
        </Item>
    </Item>
</Menu>
</Menu>
</MenuConfig>

Это XSLT, который я пытаюсь создать:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:param name="menu"/>

<xsl:template match="/MenuConfig/Menu">
    <div id="data-sidebar">
        <ul class="sidebar list-unstyled">
            <li>
            <xsl:attribute name="class">
                <xsl:if test="@name = $menu">active</xsl:if>
            </xsl:attribute>
                <xsl:element name="a">
                    <xsl:attribute name="href">
                        <xsl:value-of select="@location"/>
                    </xsl:attribute>
                    <xsl:value-of select="@title"/>
                </xsl:element>
                <ul>
                    <xsl:apply-templates/>
                </ul>
            </li>
        </ul>
    </div>
</xsl:template>

<xsl:template match="Item[not(Item)]">
    <li>
    <xsl:attribute name="class">
        <xsl:if test="@name = $menu">active</xsl:if>
    </xsl:attribute>
        <xsl:element name="a">
            <xsl:attribute name="href">
                <xsl:value-of select="@location"/>
            </xsl:attribute>
            <xsl:value-of select="@title"/>
        </xsl:element>
    </li>
</xsl:template>

<xsl:template match="Item[Item]">
    <li>
    <xsl:attribute name="class">
        <xsl:if test="@name = $menu">active</xsl:if>
    </xsl:attribute>
        <xsl:element name="a">
            <xsl:attribute name="href">
                <xsl:value-of select="@location"/>
            </xsl:attribute>
            <xsl:value-of select="@title"/>
        </xsl:element>
        <ul>
            <xsl:apply-templates select="Item" />
        </ul>
    </li>
</xsl:template>

</xsl:stylesheet>

У меня есть этот внешний параметр «меню», где я получу текущую позицию в списке (свойство имени)

Давайте представим, что параметр имени — «имя-3.4.1.2». В этом случае я должен показать только меню-3, меню-3.4, меню-3.4.1 и дочерние элементы и меню-3.4.2 (близнец 3.4.1), но без дочерних элементов. Возможно (это еще не подтверждено моим бизнес-менеджером) мне следует показать только 3 или 4 уровня предков. Например, если выбрано меню уровня 6 (1.2.3.4.5.6), я должен показывать только уровень 3 (1.2.3).

Я понятия не имею, как это сделать. Мой реальный XML глубже этого, и он может быть бесконечно глубоким.

Извините, если я недостаточно ясен, но я не могу объяснить лучше.

Спасибо, парни...

РЕДАКТИРОВАТЬ: это ожидаемый результат. Это HTML:

  <div id="data-sidebar">
        <ul class="sidebar list-unstyled">
            <li class=""><a href="location 3.jsp">Menu 3</a>
                <ul>
                    <li class=""><a href="location 3.4.jsp">Menu 3.4</a>
                        <ul>
                            <li class=""><a href="location 3.4.1">Menu 3.4.1</a>
                                <ul>
                                    <li class=""><a href="location 3.4.1.1">Menu 3.4.1.1</a></li>
                                    <li class="active"><a href="location 3.4.1.2">Menu 3.4.1.2</a></li>
                                </ul>
                            </li>
                            <li class=""><a href="location 3.4.2">Menu 3.4.2</a></li>
                        </ul
                    </li>
                </ul>
            </li>
        </ul>
    </div>

В браузере это должно выглядеть так:

  • Menu 3
    • Menu 3.4
      • Menu 3.4.1
        • Menu 3.4.1.1
        • Меню 3.4.1.2
      • Меню 3.4.2

person Adriano    schedule 02.10.2014    source источник
comment
Пожалуйста, покажите ожидаемый вывод в виде XML/XHTML, а не в виде текста — трудно представить, как должен выглядеть вывод. Кроме того, может быть, стоит подождать, пока ваш бизнес-менеджер все решит, прежде чем спрашивать здесь?   -  person Mathias Müller    schedule 02.10.2014
comment
Есть некоторые правила, что это произойдет независимо от их решений. Над этими правилами я сейчас работаю. Я поставил вывод. Теперь должно быть яснее .. спасибо   -  person Adriano    schedule 02.10.2014


Ответы (1)


Хотя это не совсем просто, я думаю, вы делаете это намного сложнее, чем нужно. Попробуйте это в качестве отправной точки:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:param name="name" select="'name-3.4.1.2'"/>

<xsl:template match="*">
    <xsl:if test="descendant-or-self::*[@name=$name]">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="*"/>
        </xsl:copy>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

Применительно к вашему примеру входных данных (с поправкой на корректность!) результат будет следующим:

<?xml version="1.0" encoding="UTF-8"?>
<MenuConfig>
   <Menu name="name-3" location="location 3" title="Menu 3">
      <Item name="name-3.4" location="location 3.4.jsp" title="Menu 3.3">
         <Item name="name-3.4.1" location="location 3.4.1.jsp" title="Menu 3.4.1">
            <Item name="name-3.4.1.2" location="location 3.4.1.2.jsp" title="Menu 3.4.1.2"/>
         </Item>
      </Item>
   </Menu>
</MenuConfig>
person michael.hor257k    schedule 02.10.2014
comment
Спасибо... Это сработало. Но мне нужен выход HTML со всеми div и т. д., а также с копией существующего XML. Извините, что спрашиваю, но я немного новичок. Спасибо - person Adriano; 02.10.2014
comment
@ Адриано, боюсь, я не понимаю, что ты имеешь в виду. Пожалуйста, отредактируйте свой вопрос и покажите как ожидаемый результат как код. - person michael.hor257k; 02.10.2014
comment
@ Адриано, я вижу. Что ж, это всего лишь вопрос изменения вывода шаблона — вместо xsl:copy выведите нужный элемент/элементы. Это не имеет ничего общего с реальной проблемой здесь, и вы извините меня, если я нахожу это совершенно неинтересным. - person michael.hor257k; 02.10.2014
comment
Хорошо.. Спасибо... Ваше решение мне очень помогло.. Я продолжу над ним работать.. Спасибо!! - person Adriano; 02.10.2014