XSLT が使用する XPath データ モデルでは、CDATA セクションを区別することはできません。これらはいずれも、テキスト ノード (の一部) として表されます。そのため、CDATA の保存は、XSLT や XPath だけでは完全に一般化することはできません。これは、DOM ベースのアプローチで実現できます。
変換の出力で、特定の名前を持つ要素のテキスト ノードに CDATA セクションが必要であり、他のセクションには必要ない場合、宣言でcdata-section-elements
属性を指定する XSLT でこれを実現できます。<xsl:output>
これがどのように行われるかの短い例を次に示します。
<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>
説明:
XSLT 命令を使用して、新しい変換を動的に生成しxsl:namespace-alias
ます。
すべての個別の要素名を決定するMuenchian グループ化。