XSLT1: преобразовать XML-узлы в Html-список, начав сначала с самого глубокого узла

#xml #xslt #xslt-1.0

#xml #xslt #xslt-1.0

Вопрос:

У меня есть это ниже xml

  <root>
        <s>
            <name>self-1</name>
            <parents>
                <s>
                    <name>p-1-2</name>
                    <parents>
                        <s>
                            <name>p-1-2-1</name>
                            <parents>
                                <s>
                                    <name>p-1-2-1-1</name>
                                </s>
                            </parents>
                        </s>
                        <s>
                            <name>p-1-2-2</name>
                        </s>
                    </parents>
                </s>
            </parents>
        </s>
    </root>
  

и мне нужно написать xslt1 для анализа этого xml, чтобы получить выходные данные, как показано ниже, цель состоит в том, чтобы сначала обработать все родительские узлы и, наконец, узел self-1. Пожалуйста, дайте мне несколько советов.

 <ul>
    <li>p-1-2-1-1</li>
    <ul>
        <li>p-1-2-1</li>
        <li>p-1-2-2</li>
        <ul>
            <li>p-1-2</li>
            <ul>
                <!-- self -->
                <li>self-1</li>
            </ul>
        </ul>
    </ul>
</ul>
  

Ответ №1:

Вот мое предложение о том, как решить эту проблему:

 <xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

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

  <xsl:template match="/">
    <xsl:apply-templates select="descendant::parents[not(s/parents)]"/>
  </xsl:template>

  <xsl:template match="parents | root">
    <ul>
      <xsl:apply-templates select="s/name"/>
      <xsl:variable name="p" select="parent::s/parent::parents | parent::s/parent::root"/>
      <xsl:if test="$p">
        <li>
          <xsl:apply-templates select="$p"/>
        </li>
      </xsl:if>
    </ul>
  </xsl:template>

  <xsl:template match="name">
    <li>
      <xsl:value-of select="."/>
    </li>
  </xsl:template>

</xsl:stylesheet>
  

Это выводит

 <ul>
   <li>p-1-2-1-1</li>
   <li>
      <ul>
         <li>p-1-2-1</li>
         <li>p-1-2-2</li>
         <li>
            <ul>
               <li>p-1-2</li>
               <li>
                  <ul>
                     <li>self-1</li>
                  </ul>
               </li>
            </ul>
         </li>
      </ul>
   </li>
</ul>
  

Это не совсем то, что вы просили, но это сделано намеренно: в вашем примере были ul элементы с ul дочерними элементами, но это не разрешено в HTML (http://www.w3.org/TR/html4/struct/lists.html#h-10.2 ). Таким образом, моя таблица стилей гарантирует, что результат является допустимым HTML, убедившись, что any ul имеет только li дочерние элементы.

Комментарии:

1. Большое спасибо, Мартин, я совершенно забыл, что могу использовать ось-потомок

Ответ №2:

для обработки нескольких узлов <s>

Я обновил шаблон <xsl:template match="parents | root"> примерно так, как показано ниже:

  <xsl:template match="parents | root">
        <ul>
            <xsl:apply-templates select="s/name"/>
            <xsl:choose>
                <xsl:when test="parent::s/parent::parents">
                    <xsl:variable name="p" select="parent::s/parent::parents"/>
                    <li><xsl:apply-templates select="$p"/></li>
                </xsl:when>

                <xsl:when test="parent::s/parent::root">
                    <xsl:variable name="p" select="parent::s/parent::root"/>
                    <li><xsl:apply-templates select="$p"/></li>
                </xsl:when>
            </xsl:choose>
        </ul>
    </xsl:template>