XSL - встроенная таблица поиска - значение поиска переменной

StackExchange, я надеюсь, что кто-то здесь может помочь мне с этой проблемой!

Я работаю в XSLT 1.0, пытаясь встроить таблицу поиска для преобразования некоторых неформатированных данных в стандартизированную отформатированную структуру.

Я читал, искал и пробовал различные методы для этого, и ни один из них не смог дать результата. (Хотя я тоже не получаю никаких ошибок.)

Ниже приведен образец XSL, с которым я работаю:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns:lookup="lookup" exclude-result-prefixes="lookup">

<xsl:key name="lookup_table" match="lookup:table/row" use="@raw"/>

<lookup:table>
    <row raw="raw1" corrected="Raw One"/>
    <row raw="raw2" corrected="Raw Two"/>
    <row raw="raw3" corrected="Raw Three"/>
    <row raw="raw4" corrected="Raw Four"/>
    <row raw="raw5" corrected="Raw Five"/>
</lookup:table>

<xsl:template match="/">

<xsl:variable name="lookup_table" select='document("")//lookup:table/row'/>
<xsl:variable name="value_to_lookup" select="'raw1'"/>

        <!-- In the actual XSL document, this variable would use an XPath to point to another attribute. -->
        <!-- In this case, the value of this variable must be changed manually. -->

<xsl:value-of select='document("")//lookup:table/row[@raw = $value_to_lookup]/@corrected'/>

<xsl:value-of select='document("")//lookup:table[@raw = $value_to_lookup]/@corrected'/>

<xsl:value-of select='$lookup_table[@raw = $value_to_lookup]/@corrected'/>

<xsl:value-of select="key('lookup_table',$value_to_lookup)/@corrected"/>

    <!-- The above lines are the various methods I've seen documented on other websites that claim these methods should allow me to what I need to. -->
    <!-- There is no need to have multiple identical results, I only have multiple attempts here to document the steps I have tried. -->

</xsl:template>
</xsl:stylesheet>

Текущий вывод этого кода - ничто (буквально).

Желаемый результат, когда переменная value_to_lookup равна "raw1":

Raw One

Для дальнейшего пояснения, желаемый результат, когда переменная value_to_lookup равна "raw4":

Raw Four

Вывод этого бита кода будет сохранен в переменной и вызван позже при необходимости.

Спасибо еще раз!


person Simcik    schedule 10.02.2016    source источник


Ответы (2)


- изменено в ответ на изменения в вопросе -

Рассмотрим 4 варианта, представленные в вашей таблице стилей:

  1. Это работает как ожидалось:

    <xsl:value-of select='document("")//lookup:table/row[@raw = $value_to_lookup]/@corrected'/>
    
  2. Это не может работать, потому что raw является атрибутом row, а row отсутствует в пути:

    <xsl:value-of select='document("")//lookup:table[@raw = $value_to_lookup]/@corrected'/>
    
  3. Это работает как ожидалось:

    <xsl:value-of select='$lookup_table[@raw = $value_to_lookup]/@corrected'/>
    
  4. Это не работает, потому что в XSLT 1.0 ключи работают только в контексте текущего документа:

    <xsl:value-of select="key('lookup_table',$value_to_lookup)/@corrected"/>
    

    Чтобы заставить его работать, вы должны сделать:

    <xsl:for-each select="document('')">
        <xsl:value-of select="key('lookup_table',$value_to_lookup)/@corrected"/>
    </xsl:for-each>
    

- добавлено в ответ на следующие пояснения в комментариях -

Таблица стилей XSL является частью приложения. Когда я хочу создать новый итоговый документ или внести изменения в существующий, я просматриваю меню приложения на основе Java. В конце концов я попал на экран с небольшим меню сбоку и большим окном для ввода текста посередине. В этом окне ввода текста набирается кодировка XSL.


что вы получите в результате <xsl:value-of select="count(document(''))"/>?


Результат - «0».

Очевидно, ваша среда обработки не поддерживает использование функции document() для ссылки на саму таблицу стилей. Это означает, что вам нужно будет использовать другой метод для выполнения внутреннего поиска, а именно определить переменную и преобразовать ее в набор узлов, как уже было предложено в ответе MiMo.

Обратите внимание, что это не имеет ничего общего с Java. Практически все процессоры XSLT 1.0 поддерживают функцию расширения EXSLT node-set(), но некоторые процессоры Microsoft распознают ее только в своем собственном пространстве имен.


Для завершения вот как вы могли бы использовать ключ для поиска значения в переменной:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:param name="value_to_lookup" select="'raw1'"/>

<xsl:key name="lookup" match="row" use="@raw"/>

<xsl:variable name="lookup">
    <row raw="raw1" corrected="Raw One"/>
    <row raw="raw2" corrected="Raw Two"/>
    <row raw="raw3" corrected="Raw Three"/>
    <row raw="raw4" corrected="Raw Four"/>
    <row raw="raw5" corrected="Raw Five"/>
</xsl:variable>
<xsl:variable name="lookup-set" select="exsl:node-set($lookup)" />

<xsl:template match="/">
    <!-- change context to the lookup "document" -->
    <xsl:for-each select="$lookup-set">
        <xsl:value-of select="key('lookup', $value_to_lookup)/@corrected"/>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
person michael.hor257k    schedule 10.02.2016
comment
Да, в этом вы правы. Мелкие изменения. Я реализовал их, а также скопировал ваш код точно так же, как указано выше, но ваш код по-прежнему не производит никакого вывода. Проблема, похоже, связана с document(''). В качестве теста, если я наберу <xsl:value-of select="$value_to_lookup"/> в тегах document(''), я не получу никаких результатов. Однако при вводе вне тегов я могу, по крайней мере, увидеть, что $value_to_lookup действительно имеет значение raw1. Предложения? - person Simcik; 11.02.2016
comment
Майкл, я пробовал это в реальном рабочем XSL-документе. Все, что было помещено в теги <xsl:for-each select="document('')">, не дало бы результата. Я вызвал некоторые из моих заведомо исправных переменных внутри тегов с помощью операторов xsl:value-of для тестирования, и они тоже ничего не показали. Кроме того, переменные, которые вы придумали, при вызове вне этих тегов, отображали правильные сохраненные значения. Это то, что заставляет меня думать, что проблема заключается в коде <xsl:for-each select="document('')">. - person Simcik; 11.02.2016
comment
Верно, и я считаю, что это делается с помощью приложения на основе Java. Таблица стилей XSL является частью приложения. Когда я хочу создать новый итоговый документ или внести изменения в существующий, я просматриваю меню приложения на основе Java. В конце концов я попал на экран с небольшим меню сбоку и большим окном для ввода текста посередине. В этом окне ввода текста набирается кодировка XSL. Полученные в результате документы применяют выбранный XSL к конкретному XML, над которым в это время работаете, а затем генерируют выходной документ на основе HTML. Это поможет ответить на вопрос? - person Simcik; 11.02.2016
comment
Майкл, используя <xsl:value-of select="system-property('xsl:vendor')" />, я получил Apache Software Foundation. Это поможет? - person Simcik; 11.02.2016
comment
Майкл, ваше обновленное решение работает! Спасибо за вашу помощь и терпение, а также за подробные ответы. Их очень ценят. С точки зрения скорости / производительности и надежности, это либо лучший выбор, либо просто предпочтение относительно того, что использовать? - person Simcik; 11.02.2016
comment
В общем, использование ключа должно быть быстрее, потому что процессор будет предварительно индексировать таблицу поиска, но я бы протестировал это в вашей конкретной ситуации, прежде чем принимать решение. - person michael.hor257k; 11.02.2016

Проблема в том, что <xsl:variable name="value_to_lookup" select='raw1'/> устанавливает value_to_lookup в значение (несуществующего) элемента raw1 - поэтому он пуст.

Вам нужно <xsl:variable name="value_to_lookup" select="'raw1'"/>, а затем <xsl:value-of select='document("")//lookup:table/row[@raw = $value_to_lookup]/@corrected'/> работает. Полный XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
            xmlns:lookup="lookup" exclude-result-prefixes="lookup">

<lookup:table>
    <row raw="raw1" corrected="Raw One"/>
    <row raw="raw2" corrected="Raw Two"/>
    <row raw="raw3" corrected="Raw Three"/>
    <row raw="raw4" corrected="Raw Four"/>
    <row raw="raw5" corrected="Raw Five"/>
</lookup:table>

<xsl:template match="/">
    <xsl:variable name="value_to_lookup" select="'raw1'"/>
    <xsl:value-of select='document("")//lookup:table/row[@raw = $value_to_lookup]/@corrected'/>
</xsl:template>

You can define the lookup table without using document() doing something like this:

<xsl:variable name="lookup_table_fragment">
    <row raw="raw1" corrected="Raw One"/>
    <row raw="raw2" corrected="Raw Two"/>
    <row raw="raw3" corrected="Raw Three"/>
    <row raw="raw4" corrected="Raw Four"/>
    <row raw="raw5" corrected="Raw Five"/>
</xsl:variable>
<xsl:variable name="lookup_table" select="msxsl:node-set($lookup_table_fragment)" />

а потом:

<xsl:value-of select='$lookup_table/row[@raw = $value_to_lookup]/@corrected'/>

(msxsl:node-set специфично для Microsoft, но у всех процессоров есть функция для преобразования фрагмента в набор узлов)

Эта последняя версия, адаптированная для процессора Java XSLT, гласит:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
        xmlns:lookup="lookup" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="lookup exsl">

    <xsl:variable name="lookup_table_fragment">
        <row raw="raw1" corrected="Raw One"/>
        <row raw="raw2" corrected="Raw Two"/>
        <row raw="raw3" corrected="Raw Three"/>
        <row raw="raw4" corrected="Raw Four"/>
        <row raw="raw5" corrected="Raw Five"/>
    </xsl:variable>
    <xsl:variable name="lookup_table" select="exsl:node-set($lookup_table_fragment)" />

    <xsl:template match="/">
        <xsl:variable name="value_to_lookup" select="'raw1'"/>
        <xsl:value-of select='$lookup_table/row[@raw = $value_to_lookup]/@corrected'/>
   </xsl:template>

</xsl:stylesheet>

и его можно протестировать на странице http://www.utilities-online.info/xsltransformation

person MiMo    schedule 10.02.2016
comment
Хорошо, это частично решило проблему. Переменная теперь правильно определена как raw1, однако окончательный вывод Raw One не отображается. - person Simcik; 11.02.2016
comment
Я добавил к ответу полный XSLT, который я использовал для тестирования - и он работает для меня - результат - это просто строка Raw One - person MiMo; 11.02.2016
comment
Ни один из ваших методов не работает. Фактически, альтернативный метод, использующий только переменные, приводит к сбою выходного листа. (Он показывает только пробелы, никакой другой контент - даже контент, который присутствовал / работал раньше.) Предложения? - person Simcik; 11.02.2016
comment
... может document() не работает в вашем XSLT-процессоре? Вторая версия использует специальную функцию Microsoft, поэтому, если у вас ее нет (и вы не определяете ее пространство имен), она не будет работать. Я добавил версию второго примера с использованием расширений Java и URL-адреса, по которому его можно протестировать. - person MiMo; 11.02.2016
comment
Пространство имен msxsl было объявлено в фактическом XML-документе как xmlns:msxsl="urn:schemas-microsoft-com:xslt", поэтому, возможно, вы что-то знаете о том, что процессор является ограничением. Я буду экспериментировать с версией на основе Java. - person Simcik; 11.02.2016
comment
Отличные новости! Версия на основе Java работает отлично! Для справки в будущем, можете ли вы понять из этого что-нибудь об ограничениях процессора? Такая информация может пригодиться в будущем ... - person Simcik; 11.02.2016
comment
Какой процессор вы использовали? Думаю, не понравилось document("") - person MiMo; 11.02.2016
comment
Я обнаружил, с некоторой помощью Майкла в его ответе, что процессор является процессором Apache Xalan и что document() не будет работать с ним, поскольку результат <xsl:value-of select="count(document(''))"/> равен 0. - person Simcik; 11.02.2016
comment
Использовал это, чтобы ответить на мой аналогичный вопрос здесь:. stackoverflow.com/questions/59415629/. Я просто добавил параметр к вызову шаблона. - person NealWalters; 19.12.2019