XSLT 2.0 обрабатывает неверный узел, смешивающий текст и cdata - PullRequest
1 голос
/ 16 ноября 2010

Мне нужно проанализировать следующий узел:

  <media:keywords>keyword1,keyword2<![CDATA[keyword3]]></media:keywords>

в правильную строку, предпочтительно «ключевое слово1, ключевое слово2, ключевое слово3», но я бы согласился полностью удалить cdata.

Попытка доступа к узлу дает мне текст «keyword1, keyword2keyword3», и я не могу сказать, где начинается CDATA.

оригинальный xml (упрощенная версия mRSS-фида)

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
     <item>
      <media:keywords>keyword1,keyword2<![CDATA[keyword3]]></media:keywords>
    </item>
  </channel>
</rss>

xsl (упрощенно):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:media="http://search.yahoo.com/mrss/" exclude-result-prefixes="xs xsi fn">
    <xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <test>
            <xsl:variable name="items" select="/rss/channel/item"/>
            <xsl:for-each select="$items">
                <xsl:variable name="mediakw" select="media:keywords"/>
                <xsl:element name="mediaKeyWords">
                        <xsl:value-of select="$mediakw"/>
                </xsl:element>
            </xsl:for-each>
        </test>
    </xsl:template>
</xsl:stylesheet>

и вывод:

<test xmlns:media="http://search.yahoo.com/mrss/"><mediaKeyWords>keyword1,keyword2keyword3</mediaKeyWords></test>

Большое спасибо!

Ответы [ 3 ]

2 голосов
/ 16 ноября 2010

XML и XSLT здесь вам не помогут .

XSLT использует модель INFOSET, в которой нет ничего в качестве «узла CDATA» , и существуеттолько один узел text ():

"keyword1, keyword2keyword3"

Необходимо исправить XML-документ и вставить запятую между подстроками "keyword2" и"keyword3"

Одним из решений было бы для обработки узла CDATA DOM с использованием DOM и только затем инициирование преобразования XSLT.

2 голосов
/ 16 ноября 2010

Нельзя сделать в стандартном XSLT.

Входной XML, который вы получаете,

<media:keywords>keyword1,keyword2<![CDATA[keyword3]]></media:keywords>

неотличимо (от XSLT) от

<media:keywords>keyword1,keyword2keyword3</media:keywords>

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

Решением было бы сообщить тем, кто предоставляет этот XML, что им необходимо поместить разделитель между keyword2 и keyword3.

2 голосов
/ 16 ноября 2010

К тому времени, когда процессор XSLT видит текст, CDATA уже нет. Вы не можете видеть входящие CDATA и очень мало контролируете, как генерируется выходной CDATA (все или ничего для данного тега).

...