Как получить CDATA из xml-узла с помощью xsl?

Я пытаюсь получить CDATA содержимое XML-узла с помощью XSL. Этот узел в настоящее время выглядит так:

<node id="1" text="Book Information" ><![CDATA[This is sample text]]></node>

мне нужно This is sample text кусок. Кто-нибудь знает об этом?

спасибо заранее.

5 ответов


Ну, если я использую эту таблицу стилей:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:template match="node/text()">
    <xsl:copy/>
  </xsl:template>
</xsl:stylesheet>

в этом XML-файле:

<?xml version="1.0" encoding="utf-8"?>
<node id=1 text="Book Information" ><![CDATA[This is sample text]]></node>

Я получаю ошибку разбора, потому что id=1 является недопустимым XML.

размещение кавычек вокруг значения атрибута (id="1") и повторный запуск таблицы стилей, я получаю в качестве вывода:

это образец текста

итак, есть начало. В принципе, просто рассматривайте CDATA как текстовый узел, и вы на своем пути.

вы сказал:

Я нашел что-то вроде:
<xsl:output cdata-section-elements="text"/>
и затем, чтобы принести CDATA:
<xsl:value-of select="node" />

этот подход отлично работает, если вы используете value-of как хорошо. Вот пример вдоль строк вашего комментария, используя . Заметьте, однако, что cdata-section-elements работает только на выходе, указывая, что выход XML-элементы, которые вы хотите напечатать, как разделы CDATA вместо обычного старого персонажа данные. Это не имеет никакого отношения к fetching данные.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output cdata-section-elements="foo"/>
  <xsl:template match="/">
    <foo>
      <xsl:value-of select="node"/>
    </foo>
  </xsl:template>
</xsl:stylesheet>

выводит

<?xml version="1.0"?>
<foo><![CDATA[This is sample text]]></foo>

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

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<catalog>
    <cd>
        <disk id="title"><![CDATA[Sample xml]]></disk >
        <disk id="artist"><![CDATA[Vijay]]></disk >
    </cd>
</catalog>


Пример файла XSL:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <h2>My CD Collection</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Title</th>
        <th>Artist</th>
      </tr>
<xsl:for-each select="catalog/cd">

      <tr>
       <td><xsl:value-of select="/catalog/cd/disk[@id='title']"/></td>
       <td><xsl:value-of select="/catalog/cd/disk[@id='artist']"/></td>
       </tr>
</xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>


Окончательный результат;
alt text


для выходных разделов CDATA:

вы должны использовать xsl:output/@cdata-section-elements. От http://www.w3.org/TR/xslt#output

атрибут cdata-section-elements содержит список, разделенный пробелами имен qname. Каждый QName расширяется в расширенное имя с использованием пространства имен заявления, касающиеся xsl: выходной элемент, в котором QName происходит; если есть значение по умолчанию пространство имен, оно используется для Имен QNames, которые не имеют приставки. Этот расширение выполняется до слияния несколько xsl: выходные элементы в a одиночный эффективный xsl: элемент выхода. Если развернуто-имя родителя текстовый узел является членом списка, затем текстовый узел должен выводиться как раздел CDATA.

кроме того Пупкин, конечно.

вы не можете выбрать разделы CDATA с XPath. Согласно http://www.w3.org/TR/xpath/#data-model

там семь типов узлов:

  • корневого узла

  • узлы элемента

  • текстовые узлы

  • узлы атрибута

  • пространства имен узлов

  • обработка узлов инструкция

  • комментарий узлов

и от http://www.w3.org/TR/xpath/#section-Text-Nodes

каждый символ в разделе CDATA рассматриваются как символьные данные. Таким образом, <![CDATA[<]]> в исходном документе будет рассматриваться так же, как <.><![CDATA[ и и все появление < и & были заменены &lt; и &amp; соответственно.


единственное решение, которое я нашел в интернете, что работает это -

{XSLT}    
<title>
    <xsl:text disable-output-escaping="yes"><![CDATA[ <![CDATA[  ]]></xsl:text>
    <xsl:value-of select="label" disable-output-escaping="yes"/>
    <xsl:text disable-output-escaping="yes"><![CDATA[]]]]><![CDATA[>]]></xsl:text>
</title>

однако это не самое чистое решение, особенно если вам нужно реализовать это в различных частях вашего XSLT. Кроме того, если ваш входной XML уже имеет CDATA (т. е. вы пытаетесь сохранить CDATA), используя disable-output-escaping, не будет работать, так как к тому времени CDATA уже был проанализирован движком XSLT, и все, что останется, это содержимое, которое может в конечном итоге нарушить XML.

вот мой решение -

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

{C#}
public string CDATAWrap(string data)
{
    return "<![CDATA[" + data + "]]>";
}

{XSLT}     
<title>
    <xsl:value-of select="CDataType:CDATAWrap(label)" disable-output-escaping="yes" />
</title>

Я пробовал с различными комбинациями и получил решение для этого;

 <xsl:value-of select="/node/."/>