Переменная XSLT не действует как набор узлов - PullRequest
0 голосов
/ 16 октября 2019

У меня есть один XML, где некоторые необработанные значения представлены в виде набора узлов. Я хочу сделать это как переменную и использовать в дальнейшем процессе. Пожалуйста, посмотрите на материал ниже:

XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <element1>Some value in the element1</element1>
    <element2 value="&lt;sno&gt;1&lt;/sno&gt;&lt;name&gt;Amrendra&lt;/name&gt;&lt;mobile&gt;0123456789&lt;/mobile&gt;"></element2>
</root>

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:output indent="yes"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:variable name="element">
        <root>
            <xsl:value-of select="/root/element2/@value" disable-output-escaping="yes"/>
        </root>
    </xsl:variable>

    <xsl:template match="/">
        <root>
            <applytemp>
                <xsl:apply-templates select="$element/root/name"/>
            </applytemp>
            <copy-of>
                <xsl:copy-of select="$element/root/name"/>
            </copy-of>
            <value-of>
                <xsl:value-of select="$element/root/name"/>
            </value-of>
        </root>
    </xsl:template>

</xsl:stylesheet>

CURRENTOUT:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <applytemp/>
   <copy-of/>
   <value-of/>
</root>

НЕОБХОДИМЫЙ ВЫХОД:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <applytemp>Amrendra</applytemp>
   <copy-of>Amrendra</copy-of>
   <value-of>Amrendra</value-of>
</root>

Ответы [ 3 ]

1 голос
/ 16 октября 2019

У меня есть один XML, в котором некоторые необработанные значения представлены в виде набора узлов.

Нет, у вас есть экранированный фрагмент XML, представленный в виде строки. Ваша попытка удалить его с помощью disable-output-escaping не может сработать, поскольку disable-output-escaping выполняется только при записи в вывод.

Если ваш процессор поддерживает XPath / XSLT 3.0, вы можете использовать функцию parse-xml-fragment() для преобразованиястрока в дерево узлов:

XSLT 3.0

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

<xsl:variable name="elem2" select="parse-xml-fragment(/root/element2/@value)" />

<!-- identity transform -->
<xsl:mode on-no-match="shallow-copy"/>

<xsl:template match="/">
    <root>
        <applytemp>
            <xsl:apply-templates select="$elem2/name"/>
        </applytemp>
        <copy-of>
            <xsl:copy-of select="$elem2/name"/>
        </copy-of>
        <value-of>
            <xsl:value-of select="$elem2/name"/>
        </value-of>
    </root>
</xsl:template>

</xsl:stylesheet>

Результат

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <applytemp>
      <name>Amrendra</name>
   </applytemp>
   <copy-of>
      <name>Amrendra</name>
   </copy-of>
   <value-of>Amrendra</value-of>
</root>

Демо : https://xsltfiddle.liberty -development.net / ejivdH2 / 2


В более ранних версиях вам нужно сделать это в два прохода. Сначала удалите строку, используя disable-output-escaping, и сохраните результат в файл. Затем обработайте полученный файл.

1 голос
/ 16 октября 2019

измените объявление переменной, как показано ниже

<xsl:variable name="element">
    <root>
        <xsl:analyze-string select="//root/element2/@value" regex="&lt;([a-z]+)&gt;(.*?)&lt;/\1&gt;">
            <xsl:matching-substring>
                <xsl:element name="{regex-group(1)}"><xsl:value-of select="regex-group(2)"/></xsl:element>
            </xsl:matching-substring>
        </xsl:analyze-string>
    </root>
</xsl:variable>

Вывод

<root>
   <applytemp>
      <name>Amrendra</name>
   </applytemp>
   <copy-of>
      <name>Amrendra</name>
   </copy-of>
   <value-of>Amrendra</value-of>
</root>

См. Преобразование на https://xsltfiddle.liberty -development.net / bFWR5DZ

0 голосов
/ 16 октября 2019

Использование отключения-вывода-экранирования при записи в переменную является давним источником проблем и противоречий, известных в рабочей группе XSL как проблема «липкого дела». Спецификация XSLT 1.0 гласит (в §16.4)

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

Но Erratum E2 сообщает:

Когда корневой узел копируется с использованием элемента xsl: copy-of (см. [11.3 Использование значений переменных и параметров с xsl: copy-of]) и экранирование было отключено для потомка текстового узла этого корневого узла, тогда экранирование также должно быть отключено для результирующей копии этого текстового узла. Например,

<xsl:variable name="x">
  <xsl:text disable-output-escaping="yes">&lt;</xsl:text>
</xsl:variable>
<xsl:copy-of select="$x"/>

должен выдавать <, а не &lt;.

То есть свойство disable-output-escaping имеет значение «sticky»: он сохраняется в переменной и повторно появляется после завершения копирования.

Это было отменено в XSLT 2.0: см. приложение J.1.4, позиция 20:

Ошибка дляВ XSLT 1.0 определено то, что стало известно как «липкое отключение-выход-экранирование»: в частности, что должна быть возможность использовать отключение-вывод-экранирование при записи узла во временное дерево, и что эта информация будет сохранена для использования приэтот же узел был позже скопирован в дерево конечных результатов и сериализован. XSLT 2.0 больше не определяет это поведение (хотя оно разрешает это по усмотрению реализации).

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

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