3

私はxmlにxsltを適用することを含むプロジェクトに取り組んでいます。

私の入力xmlには、xmlノードのいずれかに「CDATA」が含まれています。

今私が欲しいのは、入力がある場合は「CDATA」を保持することです

disable-output-escaping や cdata-section-elements などの多くのソリューションを試しましたが、私の要件に適したものはありませんでした。

それで、私ができる方法はありますか?? 入力 xml ノードに cdata がある場合、入力 xml ノードに cdata がない場合、出力にそれを与える必要があります。出力に与えるべきではありません。

私は、cdata を含むノードと、cdata を含まない diff の場所にある別のノードを呼び出しました。

<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 を含み、どこにでも来ることができるということは修正されていません

4

2 に答える 2

7

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>

説明:

  1. XSLT 命令を使用して、新しい変換を動的に生成しxsl:namespace-aliasます。

  2. すべての個別の要素名を決定するMuenchian グループ化。

于 2013-03-29T04:43:48.293 に答える