tags:

views:

43

answers:

3

I need to display HTML-element in comments (for example)

<!-- <img src="path" width="100px" height="100px"/> -->

I use this approach

<?xml version="1.0" encoding="windows-1251"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
<xsl:output method="html" indent="no" encoding="windows-1251"/>

    <xsl:template match="myNode">
        ...
        <xsl:comment><xsl:apply-templates select="image" /></xsl:comment>
        ...
    </xsl:template>

    <xsl:template match="image">
        <img src="{@src}" width="{@width}px" height="{@height}px" />
    </xsl:template>

</xsl:stylesheet>

As a result:

<!---->

that is the code in the element xsl:comment ignored.

How do I display an item in the comments?

+1  A: 

From http://www.w3.org/TR/xslt#section-Creating-Comments:

The xsl:comment element is instantiated to create a comment node in the result tree. The content of the xsl:comment element is a template for the string-value of the comment node.

For example, this

<xsl:comment>This file is automatically generated. Do not edit!</xsl:comment>

would create the comment

<!--This file is automatically generated. Do not edit!-->

It is an error if instantiating the content of xsl:comment creates nodes other than text nodes. An XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the offending nodes together with their content.

It is an error if the result of instantiating the content of the xsl:comment contains the string -- or ends with -. An XSLT processor may signal the error; if it does not signal the error, it must recover by inserting a space after any occurrence of - that is followed by another - or that ends the comment.

So, in order to do what you want you need to use DOE mechanism.

As example, this stylesheet:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes="msxsl">
    <xsl:output method="html" indent="no" encoding="windows-1251"/>
    <xsl:template match="img">
        <img src="{.}"/>
    </xsl:template>
    <xsl:template match="root">
        <xsl:variable name="vResult">
            <xsl:apply-templates/>
        </xsl:variable>
        <html>
            <xsl:copy-of select="$vResult"/>
            <xsl:comment>
                <xsl:apply-templates select="msxsl:node-set($vResult)"
                                     mode="encode"/>
            </xsl:comment>
        </html>
    </xsl:template>
    <xsl:template match="*" mode="encode">
        <xsl:value-of select="concat('&lt;',name())"
                      disable-output-escaping="yes"/>
        <xsl:apply-templates select="@*" mode="encode"/>
        <xsl:text>></xsl:text>
        <xsl:apply-templates mode="encode"/>
        <xsl:value-of select="concat('&lt;',name(),'>')"
                      disable-output-escaping="yes"/>
    </xsl:template>
    <xsl:template match="*[not(node())]" mode="encode">
        <xsl:value-of select="concat('&lt;',name())"
                      disable-output-escaping="yes"/>
        <xsl:apply-templates select="@*" mode="encode"/>
        <xsl:text>/></xsl:text>
    </xsl:template>
    <xsl:template match="@*" mode="encode">
        <xsl:value-of select="concat(' ',name(),'=&quot;',.,'&quot;')"/>
    </xsl:template>
</xsl:stylesheet>

With this input:

<root>
    <img>http://example.org/image1.jpg&lt;/img&gt;
    <img>http://example.org/image2.jpg&lt;/img&gt;
    <img>http://example.org/image3.jpg&lt;/img&gt;
</root>

Output:

<html>
    <img src="http://example.org/image1.jpg"&gt;
    <img src="http://example.org/image2.jpg"&gt;
    <img src="http://example.org/image3.jpg"&gt;
    <!--<img src="http://example.org/image1.jpg"/&gt;
        <img src="http://example.org/image2.jpg"/&gt;
        <img src="http://example.org/image3.jpg"/&gt;--&gt;
</html>

Note: node-set extension function for two pass transformation. disable-output-escaping attribute for xsl:value-of instruction.

Alejandro
@Alejandro: I can not use `node-set` in our project (I have no way to activate this feature)
Kalinin
@Kalinin: The use of `node-set` extension function is about two pass transformation, it's not about what you need: disabling output escaping so `<` character isn't output as an entity reference `<`. Of course, if you don't use a two pass transformation you have to built the contente template for your "pseudoelements" the same way I did in those mode "encode" templates. Also, I'm sure your processor has the `node-set` extension function but under a diferent namespace. Which XSLT processor do you use?
Alejandro
+1  A: 

It might be possible to replace

<xsl:comment><xsl:apply-templates select="image" /></xsl:comment>

with

<xsl:text disable-output-escaping="yes">&lt;!--</xsl:text>
<xsl:apply-templates select="image" />
<xsl:text disable-output-escaping="yes">--&gt;</xsl:text>

Haven't tried though.

Michael
+1  A: 
<xsl:comment><xsl:apply-templates select="image" /></xsl:comment>

As a result:

<!---->

that is the code in the element xsl:comment ignored

The XSLT 1.0 Spec says:

It is an error if instantiating the content of xsl:comment creates nodes other than text nodes. An XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the offending nodes together with their content.

How do I display an item in the comments?

It depends what is meant for "display": in a browser:

&lt;-- <xsl:apply-templates select="image" /> -->

may be useful, provided the result of <xsl:apply-templates/> aboveis just simple text (not markup).

If to "display" means to provide the result as text, then DOE, if allowed by the XSLT processor, may give us the wanted result:

<-- Some text -->

Finally, if it is required that what should be inside the "comment" should be markup and it should be displayed as markup, then this is rather challenging. In this case one has to use:

<xsl:output method="text"/>

and should present every XML lexical item with its desired serialization (i.e. escaped).

This is how the XPath Visualizer constructs its output.

Here is a small transformation that demonstrates the first two approaches:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
      &lt;-- Hello, World -->

  <xsl:text disable-output-escaping="yes">&lt;--</xsl:text>
   Hello,world! --<xsl:text disable-output-escaping="yes">&gt;</xsl:text>
 </xsl:template>
</xsl:stylesheet>

this transformation, when applied on any XML document (not used), produces:

      &lt;-- Hello, World --&gt;

  <--
   Hello,world! -->

Both "comments" may be viewed as comments in a browser, while only the second is presented as comment in free text.

The third approach (most probably what you want) is illustrated below:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  &lt;-- <xsl:apply-templates select="image"/> -->

 </xsl:template>

 <xsl:template match="image">
  &lt;img src="<xsl:value-of select="@src"/>"
      width="<xsl:value-of select="@width"/>px"
      height="<xsl:value-of select="@height"/>px"/>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the following XML document:

<image src="http://xxx.com/yyy.jpg" width="200" height="300"/>

the wanted result is produced:

  &lt;-- 
  &lt;img src="http://xxx.com/yyy.jpg"
      width="200px"
      height="300px"/&gt;
  --&gt;

viewed in a browser as:

<-- <img src="http://xxx.com/yyy.jpg" width="200px" height="300px"/> -->

Dimitre Novatchev