Как пройти XML-файл на основе переменных с XSL - PullRequest
1 голос
/ 16 февраля 2011

Я недавно задал вопрос, на каком движке анализировать мой xml, и решил придерживаться XSL, но я могу выполнить работу только наполовину.(ref: Какой язык использовать для анализа xml для навигации )

Мне удалось добраться до обхода <root> --> <menu> --> <nav>, но все дети, находящиеся под навигацией, и моя логика полностью облажалисьвверх.

Вопрос в том, как мне повторить мою логику в xsl, чтобы глубже проникнуть в дочерние узлы xml, когда @path - следующий уровень дочерних узлов?

Я даже делаю это правильно?Мне кажется, что я что-то здесь упускаю и должен каким-то образом использовать шаблоны?

Например, вот моя таблица стилей xsl.

<?xml version="1.0" encoding="UTF-8"?>
<!--
    Document   : sitemap.xsl
    Created on : 2 February 2011, 14:53
    Author     : Jared
    Description:
        Purpose of transformation follows.
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" />
    <xsl:param name="page" select="default"/>

    <xsl:template match="root">
        <ul class="level-0 top-level">
            <xsl:for-each select="*/nav">
                <xsl:choose>
                    <xsl:when test="$page = '/index.aspx'">
                        <!-- level 0 -->
                        <li>
                            <a><xsl:attribute name="href"><xsl:value-of select="@path" /></xsl:attribute><xsl:value-of select="@name" /></a>
                        </li>
                    </xsl:when>

                    <xsl:when test="@path=$page and $page != '/index.aspx'">
                        <!-- level 2 -->
                        <li class="children-open current-menu-page">
                            <a><xsl:attribute name="href"><xsl:value-of select="@path" /></xsl:attribute><xsl:value-of select="@name" /></a>
                            <ul class="level-2 current-menu">
                                <xsl:for-each select="/root/menu/nav[@path=$page]/child::*">
                                    <li>
                                        <a><xsl:attribute name="href"><xsl:value-of select="@path" /></xsl:attribute><xsl:value-of select="@name" /><br /></a>
                                    </li>
                                </xsl:for-each>
                            </ul>
                        </li>
                    </xsl:when>


                    <xsl:otherwise>
                        <li>
                            <a><xsl:attribute name="href"><xsl:value-of select="@path" /></xsl:attribute><xsl:value-of select="@name" /></a>
                        </li>
                    </xsl:otherwise>


                </xsl:choose>

            </xsl:for-each>

        </ul>
    </xsl:template>

</xsl:stylesheet>

Файл XML выглядит примерно так:

<root name="menutest">
  <menu>
      <nav name="home" path="index.php" />

      <nav name="menulink1" path="link1.php">
          <nav name="menulink1child1" path="menulink1childlink1.php">
             <nav name="menulink1child1child1"
                  path="menulink1childlink1childlink1.php" />
          </nav>
      </nav>

      <nav name="menulink2" path="link2.php">
         <nav name="menulink1child2" path="menulink2childlink2.php">
            <nav name="menulink2child2child2"
                 path="menulink2childlink2childlink2.php" />
         </nav>
      </nav>

      <nav name="menulink3" path="link3.php">
         <nav name="menulink3child3" path="menulink3childlink3.php">
             <nav name="menulink3child3child3"
                  path="menulink3childlink3childlink3.php" />
         </nav>
      </nav>

      <nav name="menulink4" path="link4.php">
         <nav name="menulink4child4"
              path="menulink4childlink4.php">
             <nav name="menulink4child4child4"
               path="menulink4childlink4childlink4.php" />
         </nav>
      </nav>
  </menu>
</root>

Это в основном показывает только детей первого уровня <nav>, основанных на параметре "$ page".Пример (ы) того, как работает меню и какие узлы выбраны, в основном выровненные <nav> узлы являются дочерними, узлы с отступом - дочерними по отношению к родителям и т. Д. И т. Д. И т. Д. xml пример http://fraudo.orconhosting.net.nz/xml.png

TIA Jared

Обновлен фрагмент кода

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" />
    <xsl:param name="page" select="'index.aspx'"/>

    <xsl:template name="makeUL">
        <ul class="level-2 current-menu">
            <xsl:apply-templates/>
        </ul>
    </xsl:template>
    <xsl:template match="nav">

            <li>
            <xsl:if test=".//@path = $page and $page != '/index.aspx'">
                <xsl:attribute name="class"><xsl:text>children-open current-menu-page</xsl:text></xsl:attribute>
             </xsl:if>
            <a href="{@path}">
                <xsl:value-of select="@name" />
            </a>
            <xsl:if test=".//@path = $page and $page != '/index.aspx'">
                 <xsl:call-template name="makeUL"/>
            </xsl:if>
        </li>

    </xsl:template>
</xsl:stylesheet>

Я также выводю "ul" перед разбором xml, но я могу ошибаться:).

echo '<ul class="level-0 top-level">'."\n\r";
    echo $xsl->transformToXML($dom);
echo '</ul>'."\n\r";

Ответы [ 2 ]

2 голосов
/ 17 февраля 2011

Если вы хотите развернуть ветвь дерева, содержащую указанный узел, эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" />
    <xsl:param name="page" select="'menulink1childlink1.php'"/>
    <xsl:template match="menu" name="makeUL">
        <ul>
            <xsl:apply-templates/>
        </ul>
    </xsl:template>
    <xsl:template match="nav">
        <li>
            <a href="{@path}">
                <xsl:value-of select="@name" />
            </a>
            <xsl:if test=".//@path = $page">
                <xsl:call-template name="makeUL"/>
            </xsl:if>
        </li>
    </xsl:template>
</xsl:stylesheet>

Выход:

<ul>
    <li><a href="index.php">home</a></li>
    <li><a href="link1.php">menulink1</a>
        <ul>
            <li><a href="menulink1childlink1.php">menulink1child1</a>
                <ul>
                    <li><a href="menulink1childlink1childlink1.php"
                          >menulink1child1child1</a></li>
                </ul>
            </li>
        </ul>
    </li>
    <li><a href="link2.php">menulink2</a></li>
    <li><a href="link3.php">menulink3</a></li>
    <li><a href="link4.php">menulink4</a></li>
</ul>

Вынесено:

  • дом
  • menulink1
    • menulink1child1
      • menulink1child1child1
  • menulink2
  • menulink3
  • menulink4

Примечание: Это единственный случай, когда может пригодиться сокращение .//.

2 голосов
/ 16 февраля 2011

Основная причина вашей проблемы в том, что вы пытаетесь использовать обработку «по запросу» - традиционные конструкции, такие как xsl: for-each и xsl: выбирать, вместо того, чтобы писать «путь XSLT» с использованием правил шаблона и xsl: apply-templates.Обычно можно написать свой код в стиле «тянуть», но эксперты избегают этого, потому что это приводит к таким неприятностям.

Я говорю «обычно», но один случай, когда это невозможнокогда ваши входные данные являются рекурсивными (элементы nav внутри элементов nav, неопределенно вложенные).Вы можете обрабатывать только рекурсивные данные, используя рекурсивный код, и в этой ситуации стиль кодирования apply-templates становится существенным.Сядьте с руководством и прочитайте несколько примеров, пока вы не поймете концепцию, а затем используйте ее в своем коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...