Уплощение глубоко вложенной структуры в XSLT - PullRequest
2 голосов
/ 16 декабря 2009

Я пытаюсь выучить XSLT (для веселого программирования). Я думаю, что теперь у меня есть довольно хорошее понимание основ (захват поддеревьев, элементов фильтрации и переименования элементов) У меня проблемы, когда дело доходит до радикальной реорганизации XML-структур. Если бы у вас была глубоко вложенная структура, и вы хотели бы сгладить ее, как бы вы это сделали?

Например, допустим, я пытаюсь преобразовать фрагмент документа в html ...

ввод (документация):

<section>
  <title>Title A</title>
  <para>foo</para>
  <para>bar</para>
  <section>
    <title>Title B</title>
    <para>baz</para>
    <para>biz</para>
    <section>
      <title>Title C</title>
      <para>bing</para>
    </section>
  </section>
  <section>
    <title>Title D</title>
    <para>fizzle</para>
  </section>
</section>

вывод (html):

<h1>Title A</h1>
<p>foo</p>
<p>bar</p>
<h2>Title B</h2>
<p>baz</p>
<p>biz</p>
<h3>Title C</h3>
<p>bing</p>
<h2>Title D</h2>
<p>fizzle</p>

Это где xsl:param и xsl:call-template вступают в игру?

Спасибо!

Ответы [ 2 ]

6 голосов
/ 16 декабря 2009

Контрольный пример Карстена работает (с незначительными корректировками, вам нужно завершить xsl:value-of с помощью /), но всегда используется <h2> в качестве заголовка. Если вы хотите использовать разные элементы заголовка в соответствии с уровнем вложенности заголовка, вам нужно что-то в дополнение к этому:

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

  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates />
      </body>
    </html>
  </xsl:template>

  <xsl:template match="title">
    <xsl:choose>
      <xsl:when test="count(ancestor::section) = 1">
        <h1><xsl:value-of select="." /></h1>
      </xsl:when>
      <xsl:when test="count(ancestor::section) = 2">
        <h2><xsl:value-of select="." /></h2>
      </xsl:when>
      <xsl:otherwise>
        <h3><xsl:value-of select="." /></h3>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="para">
    <p><xsl:value-of select="." /></p>
  </xsl:template>

</xsl:stylesheet>

Функция XPath count(ancestor::section) вернет счетчик всех <section> элементов, которые являются родителями текущего элемента. В этом примере я использовал <h1> и <h2> для двух самых внешних уровней и <h3> для чего-либо более глубокого вложенного, но, конечно, вы можете использовать другие отличия при вашем расстройстве.

Можно даже сгенерировать число после заголовка на лету, используя это выражение:

  <xsl:template match="title">
    <xsl:variable name="heading">h<xsl:value-of select="count(ancestor::section)" /></xsl:variable>
    <xsl:element name="{$heading}">
      <xsl:value-of select="." />
    </xsl:element>
  </xsl:template>

Секция xsl:variable создает переменную со значением h + уровень вложенности. Затем переменную можно использовать в качестве параметра для элемента xsl:element, который позволяет динамически определять имя элемента, который вы хотите создать.

Продолжение: Если вы хотите использовать только h1-h6, как предложено, вы можете сделать это так:

<xsl:template match="title">
  <xsl:variable name="hierarchy" select="count(ancestor::section)"/>
  <xsl:variable name="heading">h<xsl:value-of select="$hierarchy" /></xsl:variable>

  <xsl:choose>
    <xsl:when test="$hierarchy > 6">
      <h6 class="{$heading}"><xsl:value-of select="." /></h6>
    </xsl:when>
    <xsl:otherwise>
      <xsl:element name="{$heading}">
        <xsl:value-of select="." />
      </xsl:element>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

Это выражение использует <h6 class="h..."> для всего, что имеет вложенность глубже 6. Оно использует <h1> - <h6> для всех других уровней иерархии.

1 голос
/ 16 декабря 2009

это должно сделать работу:

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

    <xsl:template match="/">
            <html><header>
              <xsl:apply-templates/>
            </header></html>
    </xsl:template>

    <xsl:template match="title">
        <h2><xsl:value-of select="." /></h2>
    </xsl:template>

    <xsl:template match="para">
        <p><xsl:value-of select="." /></p>
    </xsl:template>
  </xsl:stylesheet>

Для выравнивания вам не нужен шаблон вызова. Если вы используете call-template, вы передаете некоторые атрибуты, см. здесь

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