Subject: Re: [xsl] Wrapping all elements in CDATA From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Thu, 22 Apr 2004 09:50:35 +0100 |
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/
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Wrapping all elements in CDAT, Jesse Wolff | Thread | RE: [xsl] Wrapping all elements in , Jesse Wolff |
[xsl] Remove a particluar Attribute, Animesh Sharma | Date | Re: [xsl] Remove a particluar Attri, Jeni Tennison |
Month |