Как получить CDATA с узла xml, используя xsl? - PullRequest
6 голосов
/ 03 июня 2010

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

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

Мне нужен кусок This is sample text. У кого-нибудь есть идеи по этому поводу?

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

Ответы [ 5 ]

10 голосов
/ 03 июня 2010

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

<?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. Вот пример вашего комментария с использованием value-of. Обратите внимание, что cdata-section-elements работает только на стороне вывода, указывая, какие выводят XML-элементы, которые вы хотите распечатать в виде разделов CDATA вместо простых старых символьных данных. Это не имеет ничего общего с извлечением данных.

<?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>
1 голос
/ 01 ноября 2010

Некоторые другие простые шаги для достижения этого;
Используется 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

0 голосов
/ 18 октября 2016

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

{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), использование escape-escape-escape не будет работать, поскольку к тому времени 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>
0 голосов
/ 01 ноября 2010

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

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

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

Кроме DOE , конечно.

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

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

  • корневые узлы

  • узлы элементов

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

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

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

  • узлы инструкций по обработке

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

А с http://www.w3.org/TR/xpath/#section-Text-Nodes

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

0 голосов
/ 24 июня 2010

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

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