Как выбрать узлы в дереве, разметка которых хранится в переменной? - PullRequest
3 голосов
/ 25 августа 2010

Рассмотрим следующий скрипт XSLT:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text" encoding="iso-8859-1"/>

<xsl:variable name="stringmap">
<map>
<entry><key>red</key><value>rot</value></entry>
<entry><key>green</key><value>gruen</value></entry>
<entry><key>blue</key><value>blau</value></entry>
</map>
</xsl:variable>

<xsl:template match="/">
<!-- IMPLEMENT ME -->
</xsl:template>

</xsl:stylesheet>

Я бы хотел, чтобы этот скрипт напечатал redgreenblue.

Есть ли способ трактовать разметку XML, которая хранится в переменной stringmap, как отдельный документ, на котором я могу выполнять запросы XPath? Я в основном ищу что-то вроде

<xsl:for-each select="document($stringmap)/map/entry">
    <xsl:value-of select="key"/>
</xsl:for-each>

(за исключением того, что функция document() ожидает URI).

Мотивация: у меня есть различные длинные <xsl:choose> элементы, которые отображают данную строку в другую строку. Я хотел бы заменить все это одним шаблоном, который принимает аргумент map (это простой XML-документ). Я надеюсь, что тогда я смогу заменить <xsl:choose> на простое утверждение вроде <xsl:value-of select="$stringmap/map/entry/value[../key='$givenkey']"/>

Я использую XSLT 1.0, используя xsltproc .

Ответы [ 2 ]

5 голосов
/ 25 августа 2010

Вы почти правы, использование document('') позволит вам обрабатывать наборы узлов внутри текущей таблицы стилей:

<xsl:for-each select="document('')/xsl:stylesheet/xsl:variable[@name='stringmap']/map/entry">
    <xsl:value-of select="key"/>
</xsl:for-each>

Нет необходимости определять набор map как переменную в этом случае:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:data="some.uri" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <data:map>
    <entry><key>red</key><value>rot</value></entry>
    <entry><key>green</key><value>gruen</value></entry>
    <entry><key>blue</key><value>blau</value></entry>
  </data:map>

  <xsl:template match="/">
    <xsl:for-each select="document('')/xsl:stylesheet/data:map/entry">
      <xsl:value-of select="key"/>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

Если вы не используете xsl:variable в качестве оболочки, вы должны помнить, что элементы верхнего уровня должны иметь ненулевой URI пространства имен.

В XSLT 2.0 можно было бы просто перебирать содержимое переменной:

<xsl:variable name="map">
  <entry><key>red</key><value>rot</value></entry>
  <entry><key>green</key><value>gruen</value></entry>
  <entry><key>blue</key><value>blau</value></entry>
</xsl:variable>

<xsl:template match="/">
  <xsl:for-each select="$map/entry">
    <xsl:value-of select="key"/>
  </xsl:for-each>
</xsl:template>
0 голосов
/ 25 августа 2010

A сообщение М. Дэвида Петерсона только что научило меня, как сделать эту работу:

Для этого случая необязательно иметь <xsl:variable>. Вместо этого я могу встроить документ данных непосредственно в таблицу стилей XSL (поместив его в пространство имен для здравомыслия), а затем выбрать элементы из этого. Вот результат:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:map="uri:map">

<xsl:output method="text" encoding="iso-8859-1"/>

<map:colors>
<entry><key>red</key><value>rot</value></entry>
<entry><key>green</key><value>gruen</value></entry>
<entry><key>blue</key><value>blau</value></entry>
</map:colors>

<xsl:template match="/">
<xsl:for-each select="document('')/*/map:colors/entry">
    <xsl:value-of select="key"/>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Генерирует ожидаемый результат redgreenblue.

Хитрость в том, чтобы использовать document(''), чтобы получить дескриптор самого документа XSLT, затем *, чтобы войти в элемент верхнего уровня xsl:stylesheet, и оттуда я могу получить доступ к карте цветов.

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