Преобразование XML с помощью XSLT и сохранение CDATA (в Ruby) - PullRequest
7 голосов
/ 01 октября 2009

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

Исходный XML:

<node>
    <subNode>
        <![CDATA[ HI THERE ]]>
    </subNode>
    <subNode>
        <![CDATA[ SOME TEXT ]]>
    </subNode>
</node>

Конечный XML:

<newDoc>
    <data>
        <text>
            <![CDATA[ HI THERE ]]>
        </text>
        <text>
            <![CDATA[ SOME TEXT ]]>
        </text>
    </data>
</newDoc>

Я пробовал что-то подобное, но не повезло, все перемешалось:

<xsl:element name="subNode">
    <xsl:value-of select="." disable-output-escaping="yes"/>
</xsl:element>

Есть идеи, как сохранить CDATA?

Спасибо! Ланс

Использование ruby ​​/ nokogiri

Обновление: вот что работает.

<text disable-output-escaping="yes">&lt;![CDATA[</text>
<value-of select="normalize-space(text())" disable-output-escaping="yes"/>
<text disable-output-escaping="yes">]]&gt;</text>

Это обернет все текстовые () узлы в CDATA, что работает для того, что мне нужно, и сохранит html-теги внутри текста.

Ответы [ 3 ]

5 голосов
/ 01 октября 2009

Невозможно сохранить точную последовательность узлов CDATA, если они смешаны с простыми текстовыми узлами. В лучшем случае вы можете сделать так, чтобы все содержимое определенного элемента в выходных данных было CDATA, перечислив имя этого элемента в xsl:output/@cdata-section-elements:

<xsl:output cdata-section-elements="text"/>
3 голосов
/ 05 октября 2009

Извините, что опубликовал ответ на свой вопрос, но я нашел кое-что, что работает:


<code><text disable-output-escaping="yes">&lt;![CDATA[</text>
<value-of select="normalize-space(text())" disable-output-escaping="yes"/>
<text disable-output-escaping="yes">]]&gt;</text></code>

Это обернет все текстовые () узлы в CDATA, что работает для того, что мне нужно, и сохранит html-теги внутри текста.

0 голосов
/ 31 августа 2018

Я нашел эту статью, пытаясь решить аналогичную проблему (используя преобразование XSL, чтобы взять один файл XML и создать частичную / подмножественную копию некоторых узлов в нем, как второй файл XML). В моем случае первые XML-файлы имеют некоторые элементы, значения которых полностью заключены в блоки CDATA, потому что они являются JSON и содержат некоторую разметку форматирования HTML.

Я обнаружил, что вместо использования xsl:value-of я мог бы использовать xsl:copy-of, и, как указывает @Pavel Minaev, я мог бы сохранить исходный CDATA без изменений, перечислив каждое соответствующее имя элемента в объявлении xsl: output , Это может быть подход, который будет работать для ОП.

XML для копирования (образец):

<text_item>
  <id>100</id>
  <stem_text><![CDATA[(any string of text, including HTML)]]></stem_text>
  <answerOptions><![CDATA[{"choices":[{"label":"Atmospheric O<sub>2</sub>",
   "value":"A"},{"label":"Released CO<sub>2</sub>",
   "value":"B"}]}]]></answerOptions>
 ...
</text_item>

Соответствующие строки таблицы стилей:

<xsl:output method="xml" indent="yes" cdata-section-elements="stem_text answerOptions" />
...
<xsl:apply-templates select="//text_item" >
...
<xsl:template match="text_item">
    <xsl:element name="text_item" >
        <xsl:copy-of select="node()"  />
    </xsl:element>
</xsl:template>

Атрибут cdata-section-elements означает, что в выходных данных исходные блоки CDATA в XML, скопированные из , будут переданы как есть в выходной XML-файл при запуске преобразования. Похоже, что вы можете назвать столько элементов, сколько хотите.

В примере ОП, я полагаю, он выберет //node/subNode, а затем построит элемент с именем text, внутри newDoc/data, конечно. Его cdata-section-elements attribute будет просто ="text", в точности как у Павла.

...