См. Обновление в конце.
1, самый важный вопрос. Это возможно сделать; вопрос заключается в том, нужно ли вам вручную писать синтаксический анализатор XML в XSLT или использовать функцию расширения или есть удобное переносимое решение. Обновление: Если вы можете использовать функцию расширения Saxon's parse (), это, безусловно, ваш лучший выбор. У вас есть доступ к этому?
2 легко ответить: да, используйте преобразование идентичности . Это не сохранит все лексические детали входного XML, такие как порядок атрибутов или то, записано ли <foo/>
как <foo></foo>
. Однако он сохранит все детали, которые должны иметь значение для процессоров XML.
Но это не поможет, если вы не можете запустить 2 таблицы стилей в конвейере, верно?
3: Хм ... не сильно. Если ваш вывод будет отображаться браузером или обрабатываться чем-то другим, понимающим инструкцию обработки таблицы стилей XML , вы можете вывести один из них и надеяться (вопреки рекомендации спецификации!) На сериализацию и Разбор будет происходить между этой таблицей стилей и таблицей, которую вы связали при выводе. Но это было бы очень хрупким . Я говорю «против рекомендации спецификации», потому что здесь говорит:
Когда этот или любой другой механизм
дает последовательность из более чем одного
Таблица стилей XSLT для применения
одновременно в XML-документ, затем
эффект должен быть таким же, как
применяя одну таблицу стилей, которая
импортирует каждый член последовательности в
заказ
что означало бы, без сериализации и разбора между ними. Не рекомендуется.
Обновление : новый комментарий говорит, что вы заранее не знаете, какие элементы будут содержать разделы CDATA. Я пришел к выводу, что это означает, что вы не знаете, какие элементы будут содержать неразобранные данные (поскольку процессоры XML официально не знают или не заботятся о том, какие элементы находятся в разделах CDATA как таковые). В этом случае все ставки отключены. Как вы, возможно, знаете, процессоры XML не должны знать, какие части документа ввода XML находятся в разделах CDATA. CDATA
- это просто другой способ избежать разметки, альтернатива <
и т. Д. После того, как данные проанализированы (что не соответствует юрисдикции процессора XSLT), вы не можете сказать, как они были первоначально выражены в разметке. Левая заостренная скобка остается левой заостренной скобкой, выражается ли она как <![CDATA[ < ]]>
или <
. Как и в C, не имеет значения, указываете ли вы символ как «A» или 65 или 0x41; как только программа скомпилирована, ваш код не сможет заметить разницу.
Поэтому, если у вас нет другого способа определить, какие данные во входном документе необходимо проанализировать, то ни один из перечисленных выше методов не поможет вам: вы не можете знать, где применять saxon: parse (), ни ручной анализ, ни отключение-вывод-экранирование с помощью следующего преобразования XSLT.
Обходные:
Вы могли бы догадаться , например с test="contains(., '<')"
, какие узлы содержат неразобранные данные. (Обратите внимание, что это тесты для левой заостренной скобки, независимо от того, выражается ли она как символьная сущность, или часть раздела CDATA, или любым другим способом.) Иногда вы получаете ложные срабатывания, например, если текстовый узел содержал строку «год <2001». Или вы можете попытаться проанализировать каждый текстовый узел (очень неэффективно), а для тех, которые успешно анализируют как правильно сформированные XML-документы, выведите дерево вместо текста. </p>
Или вы можете предварительно обработать XML с помощью не-XML-инструмента (например, LexEv ), который поэтому может «видеть» разметку CDATA. Но вы сказали, что не можете ничего контролировать вне одного XSLT.
Или, в идеале, вы могли бы отправить сообщение обратно по цепочке о том, что передаваемый вами XML неработоспособен: им нужно пометить каким-либо образом, кроме как с помощью разметки CDATA, которая разделы содержат неразобранные данные. Обычно это делается либо путем указания определенных имен элементов, либо с помощью флагов атрибутов. Очевидно, это будет зависеть от того, кто предоставляет XML.
Еще одно обновление
Хорошо, теперь я понимаю: поэтому вы знаете, какой элемент содержит неразобранные данные (и вы знаете, что он помечен с помощью CDATA), но вы не знаете, какие другие данные могут быть помечены с помощью CDATA.
Идея состояла в том, чтобы преобразовать [т.е. parse -Lars] известный
Узел CDATA ("Фред") в узлы XML
оставляя все остальное
документа в качестве исходного ввода ,
чтобы потом можно было
«общее» преобразование
Для этой цели «оставление всего остального документа в качестве исходного ввода» не обязательно означает сохранение какой-либо разметки CDATA. (Общее преобразование в нисходящем направлении не будет знать или не заботиться о том, какие данные экранированы CDATA.) Все, что требуется, - это то, что один непарсированный узел будет проанализирован, а остальные - не проанализированы. преобразование идентичности прекрасно подойдет для последнего; вы можете игнорировать то, что эта страница говорит о разделах CDATA на выходе ... нижестоящий XSLT не будет знать или беспокоиться. (Если у вас нет дополнительных (не XML) требований к выходным данным, о которых вы нам не сообщили.)
Так что, если вы могли бы выполнить преобразование из двух таблиц стилей, с сериализацией и анализом между (т.е. не в традиционном конвейере SAX, например), то преобразование идентичности будет работа: вам просто нужен дополнительный шаблон для известного неразобранного узла, с отключением-выходом-экранированием, как в ответе Томалака здесь .
Но если вы не можете выполнить двухэтапное преобразование ... какой процессор XSLT вы используете? Там могут быть другие пути, специфичные для этого.