Using XSLT to output an empty HTML textarea element
Asked Answered
E

8

8

When attempting to output an empty textarea element, the .NET XSLT processor collapses the element to its short form. Instead of this:

<textarea id="blah" name="blah"></textarea>

I get this:

<textarea id="blah" name="blah"/>

Which causes many web browsers (including IE and Firefox) to render the rest of the page as if it were the contents of the textarea. This sucks.

I can force the XSLT processor to output both the opening and closing textarea tags if I place something in between like a non-breaking space. But that means I have to do more parsing and validation on the client side to tell when the textarea is "truly" empty. I also have to use JavaScript to remove the extra space so that users don't begin their comments with a blank space.

Does anyone know of a way to force the XSLT processor to render both the opening and closing tags without having to insert dummy content?

Exciter answered 16/2, 2009 at 2:7 Comment(0)
K
3

Find your answer via a similar question right here on Stackoverflow.com :-)

Here is further explanation from MSDN.

Kile answered 16/2, 2009 at 2:12 Comment(0)
C
2

I you have to use dummy content, this was the xsl:template I used, having just the Line Feed character inside the textarea.

<!-- This prevents empty textarea elements being rendered as singletons in the XHTML output by adding a newline character -->
<xsl:template name="xhtml-textarea-contents">
    <!-- what should be contained in the textarea -->
    <xsl:param name="contents" />

    <xsl:choose>
        <xsl:when test="$contents = ''"><xsl:text>&#x0A;</xsl:text></xsl:when>
        <xsl:otherwise><xsl:copy-of select="$contents" /></xsl:otherwise>
    </xsl:choose>
</xsl:template>
Caenogenesis answered 16/2, 2009 at 2:34 Comment(0)
E
1

Chris Ballance had an answer that worked for me. But it's worth noting that I had been using an overload of XslCompiledTransform that output to a stream, like so:

XslCompiledTransform transform = new XslCompiledTransform();
...
MemoryStream stream = new MemoryStream();
transform.Transform(reader, args, stream);

In order to pass the correct settings along, I had to use the overload that accepted an XmlWriter instead.

// using XmlWriter so I can pass the output settings along.
XmlWriter writer = XmlWriter.Create(stream, transform.OutputSettings);
transform.Transform(reader, args, writer);

Microsoft's using a really odd design pattern there.

Exciter answered 16/2, 2009 at 2:42 Comment(0)
W
1

If you are generating an xml or html, you can write a newline inside the textarea and then remove it with jquery.

This is an example with jQuery:

<textarea>&#160;<textarea>

<script>
 $(document).ready(function(){
    $('textarea').each(
      function(index){$(this).text('');}
     );
  });
</script>
Winded answered 1/12, 2009 at 10:20 Comment(0)
G
1

I've come across this issue outside of .net, which is reproducible [for me] in both <xsl:output method="xml"> and <xsl:output method="xhtml"> (I'm making an assumption that method="html" is inapplicable to our scenario where output has to be well-formed xml)

To avoid the textarea tag from collapsing we have to insert some content into it, but we also have to avoid tampering with actual content. The following:

<xsl:if test="not(normalize-space())"><xsl:comment></xsl:comment></xsl:if>

produces correct results (i.e. prevents empty textarea from self-closing and does not introduce artificial content). I believe this behaviour is mentioned in spec under node construction from post-schema-validation infoset, where empty comments' string values would become zero length strings; however the document's phrasing is waaay too w3-ey for light afternoon reading.

Pushing it a bit further (so if it doesn't tamper with content, do we really need xsl:if?), this is the final template that prevents certain tags from collapsing (I aspire to follow the identity transform pattern):

<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="textarea">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
        <xsl:comment></xsl:comment>
    </xsl:copy>
</xsl:template>

NB: browsers' behaviour would suggest this transformation should be applied to some other elements as well, like paragraphs. Having a self-closing <p/>, however, is not as destructive as having a self-closing <textarea/>!

Gillan answered 11/11, 2013 at 3:52 Comment(0)
J
0

I had a similar problem and just realized that if you set the ConformanceLevel of the XmlWriterSettings to Fragment, it eliminates some of the XslCompiledTransform quirks.

FileStream xmlFileStream = File.Create("file.xml");
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load("transform.xsl");
XmlWriterSettings settings = new XmlWriterSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
XmlWriter xmlWriter = XmlWriter.Create(xmlFileStream, settings);
transform.Transform(sourceXml, null, xmlWriter);
Jabiru answered 16/4, 2009 at 5:5 Comment(0)
F
0

this work for me

<xsl:template name="fillTextArea">
  <xsl:param name="sourceStr" />
    <xsl:element name="textarea">
     <xsl:attribute name="value">
       <xsl:value-of select="$sourceStr"></xsl:value-of>
         </xsl:attribute>
         <xsl:attribute name="class">notes</xsl:attribute>
     </xsl:element>
</xsl:template>
Fain answered 23/6, 2021 at 5:14 Comment(0)
B
0

try :

<textarea><xsl:text>&#x0A;</xsl:text></textarea>

or :

<textarea><xsl:text><![CDATA[]]></xsl:text></textarea>
Bramwell answered 14/2 at 11:39 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Nysa

© 2022 - 2024 — McMap. All rights reserved.