2013-03-29 2 views
2

Я работаю над проектом, который включает в себя применение некоторых xslt для xml.XML и XSLT keep CDATA

My Input xml содержит «CDATA» в любом из узлов xml.

Теперь то, что я хочу, это должно держать «CDATA», если он имеет на входе

Я пробовал много решений, как отключить-выход-отводящей и CDATA-секции-элементов и т.д. ... , но я не нашел ни одного из они подходят для моего требования.

Итак, есть ли способ, я могу это сделать ?? Если входные узлы xml имеют cdata, тогда он должен указывать его на выходе, если входные узлы xml не имеют cdata, тогда он не должен давать его на выходе.

Я узел называется, который содержит CDATA и другой узел в некотором дифф месте, которое не суммируется и не содержит CDATA ..

<Address> 
<Location> 
<Code>912</Code> 
<Value>10301</Value> 
</Location> 
<Name><![CDATA[E&S]]></Name> 
<CompanyName><![CDATA[E&S]]></CompanyName> 
<AddressLine3>dummy address</AddressLine3> 
<City>dummy city</City> 
<State>dummy state</State> 
<PostalCode>dummy postal code</PostalCode> 
<Country>dummy country</Country> 
</Address> 
<Nodes> 
<Node> 
<Type>CTU</Type> 
<Text><![CDATA[dummy text & dummy Text.]]></Text> 
</Node> 
</Nodes> 

Это не зафиксировано, что только заранее определенные узлы будут содержать CDATA он может прийти в любом месте

+0

Пожалуйста, измените вопрос и предоставить образец XML-документ (маленький), и желаемый точный результат преобразования. –

+0

Если вы знаете, какие части имеют CDATA, тогда обычно есть способ сделать это. Вы это знаете? Я не верю, что XSLT может определить, какие части были первоначально CDATA. – JLRishe

+0

Я проанализировал свой вход и то, что я нашел, если какой-либо из узлов содержит специальные символы, то cdata будет там – user2181841

ответ

5

Вот краткий пример того, как это делается:

<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="a b c d e"/> 
<xsl:strip-space elements="*"/> 

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

Когда это преобразование применяется на следующий документ XML:

<Record> 
    <a>10:30</a> 
    <b>20:30</b> 
    <c>10:60</c> 
    <d>1:15</d> 
    <e>1:03</e> 
</Record> 

разыскиваемый, правильный результат получается:

<Record> 
    <a><![CDATA[10:30]]></a> 
    <b><![CDATA[20:30]]></b> 
    <c><![CDATA[10:60]]></c> 
    <d><![CDATA[1:15]]></d> 
    <e><![CDATA[1:03]]></e> 
</Record> 

В случае множество имен элементов не известны заранее, можно использовать таблицу стилей, которая создает другую таблицу стилей, которая должна быть окончательно применена к документу XML для получения желаемого результата.:

<xsl:stylesheet version="1.0" xmlns:x="http://www.w3.org/1999/XSL/Transform" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xxx="xxx"> 
<xsl:namespace-alias stylesheet-prefix="xxx" result-prefix="xsl"/> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kElemByName" match="*[text()[normalize-space()]]" use="name()"/> 

<xsl:variable name="vDistinctNamedElems" select= 
"//*[generate-id()=generate-id(key('kElemByName',name())[1])]"/> 

<xsl:variable name="vDistinctNames"> 
    <xsl:for-each select="$vDistinctNamedElems"> 
    <xsl:value-of select="concat(name(), ' ')"/> 
    </xsl:for-each> 
</xsl:variable> 

<xsl:template match="node()|@*"> 
    <xxx:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xxx:output omit-xml-declaration="yes" indent="yes" 
     cdata-section-elements="{$vDistinctNames}"/> 
    <xxx:strip-space elements="*"/> 

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

Когда это преобразование применяется на документе же XML (выше), то результат будет другой XSLT-таблица стилей:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:x="http://www.w3.org/1999/XSL/Transform" 
       version="1.0"> 
    <xsl:output omit-xml-declaration="yes" indent="yes" cdata-section-elements="a b c d e "/> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

В этой таблице стилей все имена элементов в атрибуте cdata-section-elements, генерируются динамически (используя метод Muenchian для группировки).

Когда мы, наконец, применить полученные таким образом таблицы стилей XSLT на тот же самом документе XML, мы получаем желаемый результат:

<Record> 
    <a><![CDATA[10:30]]></a> 
    <b><![CDATA[20:30]]></b> 
    <c><![CDATA[10:60]]></c> 
    <d><![CDATA[1:15]]></d> 
    <e><![CDATA[1:03]]></e> 
</Record> 

Объяснения:

  1. Динамически производству нового преобразование, с использованием инструкции XSLT xsl:namespace-alias ,

  2. Muenchian grouping для определения всех различных наименований элементов.

+0

Большое вам спасибо за то, что вы дали свое время, но в моем случае узлы не фиксированы. поэтому я cnt поместил их в элементы cdata-section. Я пробовал это решение bt did not работает для меня :( – user2181841

+0

@ user2181841, см. обновление к моему ответу - преобразование обрабатывает XML-документ и производит другое преобразование, которое имеет точные имена и когда это преобразование применяется к XML-документу, оно производит точно желаемый результат. –

+0

эй, я пробовал ваш код, но он генерирует cdata во множестве нежелательных узлов также :(.. даже ima new bee to xslt, поэтому я не мог даже правильно понять код ur :( – user2181841

0

Ваше решение ввести имя вашего узла/элемента, который содержит cdatasection в cdata-section-elements атрибуту (uh):

<xsl:output omit-xml-declaration="yes" 
      indent="yes" 
      cdata-section-elements="Name CompanyName Text" 
/> 
+0

Извините, я не читал это правильно ....: | Это решение для меня, но не для вас. –

Смежные вопросы