2015-07-21 4 views
0

У меня есть объект XdmNode, сгенерированный преобразованием, которое мне нужно записать в поток, который включает в себя некоторые CDATA, но я не могу получить вывод, чтобы включить экранирование CDATA.Как включить CDATA при записи XdmNode Saxon в Stream в C#

Является ли это потому, что я не проходил процесс сериализации, например, используя класс Serializer? Если да, то как мне это сделать? Я вижу, что класс Serializer имеет метод serializeNode() в Java, но не в C# ... только преобразование/etc, похоже, может «использовать» его. Или это проблема вокруг инструкции cdata-section-elements?

Использование XML и XSLT здесь для иллюстрации: How do I force xslt transformation to load data into cdata sections?

Это использует .NET 4.5 с Saxon 9.6.0.6 в C#.

C# код:

Processor processor = new Processor(); 
XdmNode node = GetNode(processor); //gets XdmNode for XML doc below 
XsltTransformer transformer = GetTransformer(processor); //gets transform below 

transformer.InitialContextNode = node; 
XdmDestination output = new XdmDestination(); 
transformer.Run(output); 
string results = output.XdmNode.OuterXml; 

using (XmlWriter writer = XmlWriter.Create(Console.Out)) 
{ 
    output.XdmNode.WriteTo(writer); 
} 

XSLT:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes" 
    cdata-section-elements="num"/> 
<xsl:strip-space elements="*"/> 

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

XML:

<nums> 
    <num>01</num> 
    <num>02</num> 
    <num>03</num> 
    <num>04</num> 
    <num>05</num> 
    <num>06</num> 
    <num>07</num> 
    <num>08</num> 
    <num>09</num> 
    <num>10</num> 
</nums> 

Ожидаемый результат:

<nums> 
    <num><![CDATA[01]]></num> 
    <num><![CDATA[02]]></num> 
    <num><![CDATA[03]]></num> 
    <num><![CDATA[04]]></num> 
    <num><![CDATA[05]]></num> 
    <num><![CDATA[06]]></num> 
    <num><![CDATA[07]]></num> 
    <num><![CDATA[08]]></num> 
    <num><![CDATA[09]]></num> 
    <num><![CDATA[10]]></num> 
</nums> 

Фактический выход (как на консоли и в строке):

<nums> 
    <num>01</num> 
    <num>02</num> 
    <num>03</num> 
    <num>04</num> 
    <num>05</num> 
    <num>06</num> 
    <num>07</num> 
    <num>08</num> 
    <num>09</num> 
    <num>10</num> 
</nums> 
+0

вам нужно 'XdmDestination' по другим причинам делать? Или вы используете поиск способа записи файла с разделами CDATA и другими параметрами, определенными с помощью 'xsl: output'? В этом случае используйте http://www.saxonica.com/html/documentation/dotnetdoc/Saxon/Api/Serializer.html вместо XdmDestination. –

+0

@Martin - да, нам нужно преобразование для создания XdmNode по другим причинам (как всегда, реальная проблема, стоящая за кодом выше, намного сложнее). Если это помогает: у нас есть одна часть нашей базы кода, которая выполняет множество преобразований и работает с XdmNodes, а другая часть, которая иногда принимает некоторые из них и записывает XdmNodes в потоки (через HTTP). Это последняя область, с которой у нас проблемы: принимающая сторона (не всегда находящаяся под нашим контролем) не видит разметки CDATA (только XML), где она должна быть (воссоздана выше, поэтому мы думаем, что это потоковая передача, а не чтение) , – user426445

+0

Ну, модель данных XSLT/XPath/XQuery, которую представляет XdmNode, не знает секцию CDATA, поэтому, когда ваше преобразование создает XdmNodes, они не содержат каких-либо разделов CDATA, это синтаксический сахар на уровне сериализации, который не представлен в древовидной модели узлы. –

ответ

1

кажется, что то, что вы хотите сделать, это отправить XdmNode к Serializer, чтобы он сериализовать со свойствами, которые установлены на Serializer , Самый простой способ сделать это, вероятно, запустить фиктивный запрос:

QueryCompiler qc = Processor.NewQueryCompiler(); 
QueryEvaluator qe = qc.Compile(".").Load(); 
qe.ContextItem = xdmNode; 
qe.Run(serializer); 

Выражение XQuery «» просто возвращает элемент контекста.

К сожалению, в документации API для Serializer не указано, какую форму следует использовать для свойства CDATA_SECTION_ELEMENTS, но я думаю, что это, вероятно, последовательность разделенных пробелами QNames в нотации Кларка, то есть Q{uri}local. Или просто локальное имя, если нет пространств имен.

(Это похоже на подход, часто используемый в интерфейсе Java JAXP бега в «тождественное преобразование». Но вопрос идентичности гораздо проще.)

+0

Спасибо - мы тоже рассматривали преобразование идентичности; хорошо знать, что есть более простая альтернатива. – user426445