Search code examples
xmlxsltinternet-explorer-11

IE11 XSLT transforms <param> node into self-closing tag without closing


This question is very much relevant to this XSLT converts <image> node to <img> tag when outputiing to DOM

Consider this piece of code:

<script type="application/xml" id="data">
    <xsl:copy-of select="/*" />
</script>

This will output the contents of an XML document into of the html page. It is then very easy to parse the data from XML via javascript's DOMParser() object making it easily accessible on the webpage without any need to use XSLT to generate a webpage.

Moving <xsl:copy-of select"/*" /> between the script tags was required to prevent XSLT transformer from transforming node in XML file into tags in HTML.

This worked perfectly, until I've found out the same happens to node as well. Simply put: if XML has node, the output will be broken and unparserable like this:

enter image description here

How to prevent this behaviour? How to stop browser engine from making tag a self-closing one?

new DOMParser().parseFromString()

/\ Will not work with self-closing nodes. (CLARIFICATION: Apparently DOMParser WILL work with self-closing nodes, it's just in this case it wasn't self-closing ie - had no forward slash)


Ok so here are the files that needed to reproduce this:

test.xslt

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="html" indent="no" version="5.0" />

    <xsl:template match="/">
        <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html></xsl:text>
        <xsl:apply-templates select="root" />
    </xsl:template>

    <xsl:template match="root">
        <html>
            <head>
                <script type='application/xml'>
                    <xsl:copy-of select="/*" />
                </script>
            </head>
            <body>
                <div>qwe</div>
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet>

test.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xslt"?>

<root>
    <object>
        <text>text</text>
        <param name="name"></param>
    </object>
</root>

Open test.xml with Edge in Internet Explorer 11 compatibility mode. The "head" should countain a script with distorted xml.

enter image description here

On windows 10 you can open the Developer Tools by doing "Run (Win+R)" -> "%systemroot%\system32\f12\IEChooser.exe" after opening the xml file


Solution

  • As for my suggestion, to serialize using the library, here is how that would look (in your real use don't import over HTTP(S), use a local copy you xsl:import):

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="1.0">
    
      <xsl:import href="https://lenzconsulting.com/xml-to-string/xml-to-string.xsl"/>
    
      <xsl:output method="html" indent="no" version="5.0" doctype-system="about:legacy-doctype" />
    
      <xsl:template match="/">
        <xsl:apply-templates/>
      </xsl:template>
      
      <xsl:template match="root">
          <html>
              <head>
                  <script type='application/xml'>
                      <xsl:apply-templates select="." mode="xml-to-string"/>
                  </script>
              </head>
              <body>
                  <div>qwe</div>
              </body>
          </html>
      </xsl:template>
    
    </xsl:stylesheet>
    

    That should give you a script element which as its text/CDATA content has the serialization of the input document's root element.

    As for the way to serialize empty elements, in XML it shouldn't matter, but the library allows you to set <xsl:param name="use-empty-syntax" select="false()"/> to get e.g. <param name="name"></param>.