[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Wrapping all elements in CDATA
Hi Jesse, > I get the expected output in MSXML and other parsers but in the > latest version of Xalan (2.6.0) I get different results. What am I > doing wrong and how can I correct this to work as expected with all > parsers? The reason that this is working differently (actually, correctly) in Xalan is that Xalan isn't ignoring the whitespace-only text nodes in your XML document. As a tree, you have: Person +- "
 " <- whitespace +- ContactInfo | +- "
 " <- whitespace | +- Email | | +- "person@xxxxxxxx" | +- "
 " <- whitespace | +- Phone | | +- "111-111-1111" | +- "
 " <- whitespace +- "
" <- whitespace Your main template: > <xsl:template match="node()|@*"> > <xsl:copy> > <xsl:apply-templates select="*|@*"/> > <xsl:apply-templates select="text()"/> > </xsl:copy> > </xsl:template> tells the processor that whenever it sees any kind of node (including text nodes; the match pattern here should really be match="*|@*" to prevent it from conflicting with your other template), it should copy that node, then process all its attributes and element children, and then process all its child text nodes. So, for example, if this template is used on the ContactInfo element, you're telling the processor to first process the Email and Phone elements, and then process the child text nodes of the ContactInfo element, of which there are three, all whitespace-only. (Probably what you meant to do here is: <xsl:template match="*|@*"> <xsl:copy> <xsl:apply-templates select="@* | node()" /> </xsl:copy> </xsl:template> This will process the attributes and children of the matched element in whatever order they appear, which means you won't get all the text nodes clustered after the child elements.) Your template for text nodes: > <xsl:template match="text()"> > <xsl:value-of select="$CDATABegin" disable-output-escaping="yes"/> > <xsl:value-of select="." disable-output-escaping="yes"/> > <xsl:value-of select="$CDATAEnd" disable-output-escaping="yes"/> > </xsl:template> wraps those text nodes in the CDATA delimiters, so you get: > <ContactInfo> > <Email><![CDATA[person@xxxxxxxx]]></Email> > <Phone><![CDATA[111-111-1111]]></Phone><![CDATA[ > ]]><![CDATA[ > ]]><![CDATA[ > ]]></ContactInfo> The CDATA sections that come after the Phone element contain the whitespace. If whitespace-only text nodes aren't significant in your document (they aren't in most data-oriented XML such as yours, but are in most document-oriented XML), then you should strip them from the source tree using the <xsl:strip-space> element at the top level of the stylesheet: <xsl:strip-space elements="*" /> This tells the processor to ignore all the whitespace-only text nodes in all the elements of the document. When I saw your stylesheet, I thought the problem was going to be the disable-output-escaping, and the fact that it isn't supported in all processors. Another way of achieving your goal while avoiding disable-output-escaping would be to use the cdata-section-elements attribute on <xsl:output>, and do: <xsl:output cdata-section-elements="Email Phone" /> Unfortunately, you have to list all the elements that can contain (significant) text nodes rather than using a wildcard, so this will only work if you know the markup language that your stylesheet needs to work with. Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|