XSLT - интерпретировать значение текстового узла как запрос XPath (и использовать его при преобразовании) - PullRequest
3 голосов
/ 06 сентября 2011

Я пытался найти приличное решение для этого, но я даже не мог найти неприличное.

У меня есть XML-файл, который выглядит примерно так:

<Root>
    <Something>
        <SomethingElse>Value of SomethingElse</SomethingElse>
    </Something>

...

    <Map>
        <Node>
            <Path>/Root/Something/SomethingElse</Path>
        </Node>
    <Map>

...

</Root>

Я хочу написать XSL-преобразование, которое будет принимать элемент <Path> и использовать его значение text() в качестве запроса XPath для применения преобразования к элементу <SomethingElse>, что приведет к чему-то вроде, например:

<text>Value of SomethingElse</text>

Первое, что пришло мне в голову, было что-то вроде:

<xsl:template match="Path">
    <text><xsl:value-of select="{text()}"/></text>
</xsl:template>

но это, конечно, не работает, поскольку select не является атрибутом значения.

Я понятия не имею, как это сделать. Поиск Google дал только результаты о том, как использовать XPath для получения текстовых значений, а не наоборот.

Я также хотел бы применить дополнительные преобразования к возвращенному элементу <SomethingElse>, но это должно быть очень просто, как только я пойму, как это сделать.

Спасибо большое за то, что вы так далеко,
Slampisko

Ответы [ 2 ]

2 голосов
/ 07 сентября 2011

Хотя полная динамическая оценка XPath не входит ни в XSLT 1.0 / XPath 1.0, ни в XSLT 2.0 / XPath 2.0, можно создать реализацию XSLT 1.0 для чего-то, что будет работать довольно ограниченным образом :

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

 <xsl:template match="text()"/>

 <xsl:template match="Path" name="eval">
  <xsl:param name="pPath" select="."/>
  <xsl:param name="pContext" select="/"/>

  <xsl:choose>
   <!-- If there is something to evaluate -->
   <xsl:when test="string-length($pPath) >0">
      <xsl:variable name="vPath" select=
          "substring($pPath,2)"/>

      <xsl:variable name="vNameTest">
       <xsl:choose>
        <xsl:when test="not(contains($vPath, '/'))">
         <xsl:value-of select="$vPath"/>
        </xsl:when>
        <xsl:otherwise>
         <xsl:value-of select=
             "substring-before($vPath, '/')"/>
        </xsl:otherwise>
       </xsl:choose>
      </xsl:variable>

      <xsl:call-template name="eval">
       <xsl:with-param name="pPath" select=
         "substring-after($pPath, $vNameTest)"/>
       <xsl:with-param name="pContext" select=
        "$pContext/*[name()=$vNameTest]"/>
      </xsl:call-template>
  </xsl:when>
  <!-- Otherwise we have evaluated completely the path -->
  <xsl:otherwise>
   <xsl:copy-of select="$pContext"/>
  </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

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

<Root>
    <Something>
        <SomethingElse>Value of SomethingElse</SomethingElse>
    </Something>

...

    <Map>
        <Node>
            <Path>/Root/Something/SomethingElse</Path>
        </Node>
    </Map>

...

</Root>

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

<SomethingElse>Value of SomethingElse</SomethingElse>

Мы предполагаем следующие ограничения :

  1. Каждое выражение XPath, которое мы оцениваем, должно состоять из последовательности тестов имен, разделенных оператором XPath '/', то есть каждый шаг местоположения определяет только одно имя элемента.

  2. Оси или предикаты не могут содержаться в любом шаге местоположения.

2 голосов
/ 06 сентября 2011

В чистом XSLT 1.0 и даже 2.0 вам нужно использовать две таблицы стилей: первая берет входные данные и создает в качестве результата вторую таблицу стилей с выражением XPath, которое вы хотите использовать, а затем запускаете вторую таблицу стилей для исходного ввода.

Или вам нужно проверить, поддерживает ли ваш процессор XSLT функцию расширения для оценки строки как выражения пути, как у Saxon с http://www.saxonica.com/documentation/extensions/functions/evaluate.xml или как у AltovaXML с его altova: функция оценки http://manual.altova.com/AltovaXML/altovaxmlcommunity/index.html?xextaltova_general.htm.

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