Атрибут соответствия XSLT, а затем его элемент - PullRequest
2 голосов
/ 31 марта 2012

В моем исходном XML любой элемент может иметь атрибут @n.Если это так, я хочу вывести его до обработки элемента и всех его дочерних элементов.

Например,

<line n="2">Ipsum lorem</line>
<verse n="5">The sounds of silence</verse>
<verse>Four score and seven</verse>
<sentence n="3">
    <word n="1">Hello</word>
    <word n="2">world</word>
</sentence>

У меня есть шаблоны, соответствующие "строке",«стих», «предложение» и «слово».Если какой-либо из этих элементов имеет значение @n, я хочу вывести его перед тем, что сгенерирует шаблон элемента.

Выше может получиться что-то вроде

2 <div class="line">Ipsum lorem</span>
5 <span class="verse">The sounds of silence</span>
<span class="verse">Four score and seven</span>
3 <p class="sentence">
   1 <span class="word">Hello</span>
   2 <span class="word">world</span>
  </p>

, где шаблоныдля "line", "verse" и т. д. генерируются элементы div, span и p.

Как я должен думать об этой проблеме?- сопоставить атрибут, а затем применить шаблоны к его родителю?(Какой будет синтаксис для этого?) Поместить шаблон вызова в начало шаблона каждого элемента?(Это непривлекательно.) Что-то еще?(Возможно!)

Я попробовал несколько вещей, но получил либо бесконечный цикл, либо ничего, либо обработку атрибута, а затем потомков его родителя, но не самого родителя.

Ответы [ 2 ]

3 голосов
/ 31 марта 2012

Чтобы упростить задачу, я поместил отображение из XML в элементы HTML в структуру данных в документе (доступную через функцию document () без аргументов). Теперь нужен только один шаблон, требующий специальной обработки атрибута @n только в одном месте.

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

  <map>
    <elt xml="line" html="class"/>
    <elt xml="verse" html="span"/>
    <elt xml="sentence" html="p"/>
    <elt xml="word" html="span"/>
  </map>

  <xsl:template match="line|verse|sentence|word">
    <xsl:if test="@n"><xsl:value-of select="@n"/> </xsl:if>
    <xsl:element name="{document()/map/elt[@xml=name()]/@html}">
      <xsl:attribute name="class"><xsl:value-of select="name()"/></xsl:attibute>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>
1 голос
/ 31 марта 2012

Вот один простой способ сделать это :

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

 <xsl:template match="*/*[@n]">
  <xsl:value-of select="concat('&#xA;', @n, ' ')"/>

  <xsl:apply-templates select="self::*" mode="content"/>
 </xsl:template>

 <xsl:template match="*/*[not(@*)]">
  <xsl:apply-templates select="." mode="content"/>
 </xsl:template>

 <xsl:template match="line" mode="content">
  <div class="line"><xsl:apply-templates/></div>
 </xsl:template>

 <xsl:template match="verse | word" mode="content">
  <span class="{name()}"><xsl:apply-templates mode="content"/></span>
 </xsl:template>

 <xsl:template match="sentence" mode="content">
  <p class="sentence"><xsl:apply-templates/></p>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному документу XML:

<t>
    <line n="2">Ipsum lorem</line>
    <verse n="5">The sounds of silence</verse>
    <verse>Four score and seven</verse>
    <sentence n="3">
        <word n="1">Hello</word>
        <word n="2">world</word>
    </sentence>
</t>

желаемый, правильный результат получается:

2 <div class="line">Ipsum lorem</div>
5 <span class="verse">The sounds of silence</span>
<span class="verse">Four score and seven</span>
3 <p class="sentence">
1 <span class="word">Hello</span>
2 <span class="word">world</span>
</p>

Пояснение : правильное использование шаблонов и режимов .

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