XSLT разрешает несовпадающие теги? - PullRequest
3 голосов
/ 09 апреля 2011
<xsl:template match="location">
        <xsl:if test="not(preceding::location)">
            <table>
                <tr>
                    <th>Name</th>
                    <th>City</th>
                    <th>State</th>
                    <th>Zip Code</th>
                    <th>Country</th>
                </tr>
        </xsl:if>
        <tr>
            <td><xsl:value-of select=".//name"/></td>
            <td><xsl:value-of select=".//city"/></td>
            <td><xsl:value-of select=".//state"/></td>
            <td><xsl:value-of select=".//zip"/></td>
            <td><xsl:value-of select=".//countdy"/></td>
        </tr>
        <xsl:if test="not(following::location)">
            </table>
        </xsl:if>
    </xsl:template>

Есть ли способ разрешить несовпадающие теги в XSLT ... или есть другой способ добиться того же желаемого эффекта?

Ответы [ 4 ]

5 голосов
/ 09 апреля 2011

Как сказал Димитр, в XSLT нет способа разрешить несовпадающие теги. Однако не должно быть причины иметь несовпадающие теги.

Глядя на ваш шаблон, похоже, что вы пытаетесь создать HTML-таблицу из всех <location> элементов вашего экземпляра XML. Вы пытаетесь открыть стол в первый <location> и пытаетесь закрыть стол в последний <location>.

Самый простой способ сделать это - открыть таблицу на более высоком уровне (родитель / предок), а затем заполнить таблицу данными <location>.

Вот пример XML-файла, который имеет 3 <location> s:

<doc>
  <location>
    <name>name 1</name>
    <city>city 1</city>
    <state>state 1</state>
    <zip>zip 1</zip>
    <country>country 1</country>
  </location>
  <location>
    <name>name 2</name>
    <city>city 2</city>
    <state>state 2</state>
    <zip>zip 2</zip>
    <country>country 2</country>
  </location>
  <location>
    <name>name 3</name>
    <city>city 3</city>
    <state>state 3</state>
    <zip>zip 3</zip>
    <country>country 3</country>
  </location>
</doc>

Вот таблица стилей, которая создаст таблицу:

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

  <xsl:template match="doc">
    <!--The table is inserted here.-->
    <table>
      <tr>
        <th>Name</th>
        <th>City</th>
        <th>State</th>
        <th>Zip Code</th>
        <th>Country</th>
      </tr>
      <!--This is where we apply the templates to populate the rows.-->
      <xsl:apply-templates select="location"/>
    </table>
  </xsl:template>

  <!--This template populates the row(s).-->
  <xsl:template match="location">
    <tr>
      <td>
        <xsl:value-of select="name"/>
      </td>
      <td>
        <xsl:value-of select="city"/>
      </td>
      <td>
        <xsl:value-of select="state"/>
      </td>
      <td>
        <xsl:value-of select="zip"/>
      </td>
      <td>
        <xsl:value-of select="country"/>
      </td>
    </tr>
  </xsl:template>

</xsl:stylesheet>

Это вывод:

<table>
   <tr>
      <th>Name</th>
      <th>City</th>
      <th>State</th>
      <th>Zip Code</th>
      <th>Country</th>
   </tr>
   <tr>
      <td>name 1</td>
      <td>city 1</td>
      <td>state 1</td>
      <td>zip 1</td>
      <td>country 1</td>
   </tr>
   <tr>
      <td>name 2</td>
      <td>city 2</td>
      <td>state 2</td>
      <td>zip 2</td>
      <td>country 2</td>
   </tr>
   <tr>
      <td>name 3</td>
      <td>city 3</td>
      <td>state 3</td>
      <td>zip 3</td>
      <td>country 3</td>
   </tr>
</table>

Если по какой-то причине вам нужно было создать <table> в первом <location>, вы все равно можете это сделать. Для этого потребуется больше кода.

Следующая таблица стилей выдает тот же вывод, что и первая таблица стилей:

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

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

  <!--The table is created at the first location and
    the first row is populated.-->
  <xsl:template match="location[1]">
    <table>
      <tr>
        <th>Name</th>
        <th>City</th>
        <th>State</th>
        <th>Zip Code</th>
        <th>Country</th>
      </tr>
      <xsl:call-template name="location-row"/>
      <!--Here is where we apply the other template to populate the other rows.
        Notice we use a "mode" to differentiate the template from the generic
        "location" template.-->
      <xsl:apply-templates select="following-sibling::location" mode="not-first"/>
    </table>
  </xsl:template>

  <!--This template will output the other rows.-->
  <xsl:template match="location" mode="not-first" name="location-row">
    <tr>
      <td>
        <xsl:value-of select="name"/>
      </td>
      <td>
        <xsl:value-of select="city"/>
      </td>
      <td>
        <xsl:value-of select="state"/>
      </td>
      <td>
        <xsl:value-of select="zip"/>
      </td>
      <td>
        <xsl:value-of select="country"/>
      </td>
    </tr>
  </xsl:template>

  <!--This generic template matches locations other than the first one. 
    Basically it is consuming it so we don't get duplicate output.--> 
  <xsl:template match="location"/>

</xsl:stylesheet>
3 голосов
/ 10 апреля 2011

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

Обычно, когда мы видим подобные вещи (и большинство из нас пробовали это, когда начинали с языка), это попытка сделать группировку так, как вы это делали бы с процедурным языком, который пишет XML как текст. Вы должны погрузиться в мышление XSLT и, в частности, думать о XML как о дереве.

3 голосов
/ 09 апреля 2011

Есть ли способ разрешить несовпадение теги в XSLT

Нет .

Таблица стилей XSLT должна быть правильно сформированным документом XML .

Кроме того, если значение атрибута method для <xsl:output> указано как "xml", то на выходе всегда будет правильно сформированный фрагмент XML (или документ).

... или есть другой способ достичь тот же желаемый эффект?

Если вы определите проблему, которую хотите решить, многие люди смогут показать вам решение, которое не требует искаженного XSLT.

0 голосов
/ 28 октября 2011

Упрощенная версия проблемы, которая, на мой взгляд, является распространенной проблемой. (Меня вдохновил совет не подходить к XSLT как к процедурному языку, предварительно решив его таким образом, используя грубую силу.)

По сути, я хочу заключить строки кода в тег PRE для вывода HTML, и первая строка кода имела уникальный стиль:




    
    

    
    
</ XSL: шаблон> </ XSL: шаблон>

Мне пришлось использовать пустой шаблон (в конце), чтобы игнорировать строки 'Code_20_Block', которые уже были обработаны циклом for-each. Может быть, есть лучшее решение для этого.

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