0

I need to adapt an old XSLT file that transforms an XML file into HTML/JS. It doesn't work anymore.

Here is the original JS code generated in XSLT file :

function processVisibility(item, visible) {
    var childs = item.childNodes;
    for (var i = 0; i < childs.length; i++) {
        if ( (childs.item(i).className == "ArchiveObject") 
            || (childs.item(i).className == "Document")
            || (childs.item(i).className == "Attachment") ) {
            if (visible) {
                childs.item(i).style.display = "block";
            } else {
                childs.item(i).style.display = "none";
            }
        }   
    }
}

The string "&lt ;" is not transformed into < in the output HTML. As a result, JS code doesn't work in modern browsers.

If I replace "&lt ;" with < in the XSLT file, I get an error and that's normal. So I tried creating a variable:

<xsl:variable name="chevron">&lt;</xsl:variable>

and

function processVisibility(item, visible) {
    var childs = item.childNodes;
    for (var i = 0; i <xsl:value-of select="$chevron" disable-output-escaping="yes"/> childs.length; i++) {
        if ( (childs.item(i).className == "ArchiveObject") 
            || (childs.item(i).className == "Document")
            || (childs.item(i).className == "Attachment") ) {
            if (visible) {
                childs.item(i).style.display = "block";
            } else {
                childs.item(i).style.display = "none";
            }
        }   
    }
}

But the HTML output does not contain < but "&lt ;" How can I get < to be generated in HTML using XSLT?

I use the HTML serialization method but it doesn't work. Here is the beginning of the XSLT file:

<xsl:stylesheet version="1.0"
    xmlns:sada="sada:v1.0"
    xmlns="http://www.w3.org/1999/xhtml"
               xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:ccts="urn:un:unece:uncefact:documentation:standard:CoreComponentsTechnicalSpecification:2"
    exclude-result-prefixes="sada xsl xsd ccts">

    <xsl:output method="html" indent="yes" media-type="text/html" encoding="UTF-8"/>

    <xsl:template match="/">
        <html>
            <head>
                
                <script type="text/javascript">
function processVisibility(item, visible) {
    var childs = item.childNodes;
    for (var i=0; i&lt;childs.length; i++) {
        if ( (childs.item(i).className == "ArchiveObject") 
            || (childs.item(i).className == "Document")
            || (childs.item(i).className == "Attachment") ) {
            if (visible) {
                childs.item(i).style.display = "block";
            } else {
                childs.item(i).style.display = "none";
            }
        }   
    }
}           </script>
                <title>Standard (SADA)</title>
            </head>
            <body>
                <xsl:apply-templates />
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>``` 
and un exemple of xml source : 

```<?xml version="1.0" encoding="UTF-8"?>
<ArchiveTransfer xmlns="sada:v1.0" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" xmlns:premis="info:lc/xmlns/premis-v2" xmlns:ns4="http://www.w3.org/1999/xlink" xmlns:ns5="http://www.w3.org/2001/XMLSchema-instance" Id="_20240314211030158" ns5:schemaLocation="sada:v1.0 sada_v1-0_archivetransfer.xsd info:lc/xmlns/premis-v2 http://www.loc.gov/premis/v2/premis.xsd">
    <Date>2024-05-01T22:37:26.047+02:00</Date>
    <TransferIdentifier/>
</ArchiveTransfer>```
4
  • Does this answer help? (I have no idea, it's what came up in search): <xsl:text disable-output-escaping="yes">&lt;</xsl:text> Commented May 1, 2024 at 15:30
  • I strongly suspect that you aren't using the HTML serialilzation method. Commented May 1, 2024 at 18:10
  • I use this output method: <xsl:output method="html" indent="yes" media-type="text/html" encoding="UTF-8"/>. And tried adding: doctype-system="about:legacy-doctype". But this does not change the character. I provide a more complete example of the XSLT file below. Commented May 1, 2024 at 20:46
  • Your script element is in a namespace, to have xsl:output method="html" apply to a script element to ensure its content is treated as CDATA you need to ensure the script element is no namespace. Or use external script. Commented May 1, 2024 at 22:19

1 Answer 1

0

It is not clear what your problem is but in general, if the xsl:output method="html" and you have a script result element in no namespace and the XSLT processor is in charge of serialization it will ensure that the output of e.g.

<?xml version="1.0" encoding="utf-8"?>
<html lang="en">
  <head>
    <title>XSLT fiddle test</title>
    <script>
function processVisibility(item, visible) {
    var childs = item.childNodes;
    for (var i = 0; i &lt; childs.length; i++) {
        if ( (childs.item(i).className == "ArchiveObject") 
            || (childs.item(i).className == "Document")
            || (childs.item(i).className == "Attachment") ) {
            if (visible) {
                childs.item(i).style.display = "block";
            } else {
                childs.item(i).style.display = "none";
            }
        }   
    }
}
    </script>
  </head>
  <body>
    <h1>Test</h1>
  </body>
</html>

by e.g.

<?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="yes" version="5" doctype-system="about:legacy-doctype"/>

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

</xsl:stylesheet>

is

<!DOCTYPE html SYSTEM "about:legacy-doctype">
<html lang="en">
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-16">
    <title>XSLT fiddle test</title>
    <script>
function processVisibility(item, visible) {
    var childs = item.childNodes;
    for (var i = 0; i < childs.length; i++) {
        if ( (childs.item(i).className == "ArchiveObject") 
            || (childs.item(i).className == "Document")
            || (childs.item(i).className == "Attachment") ) {
            if (visible) {
                childs.item(i).style.display = "block";
            } else {
                childs.item(i).style.display = "none";
            }
        }   
    }
}
    </script>
  </head>
  <body>
    <h1>Test</h1>
  </body>
</html>

where you can see that the script element contains < and not &lt;.

As for the code you have added, well, it uses xsl:output method="html" in an XSLT 1.0 stylesheet but puts its result elements in the XHTML namespace instead of having them in no namespace, that way a script element in that namespace is serialized even with that output method as an XML element and according to XML rules.

If you want to use XSLT to create XHTML as text/html then you really should be using an XSLT 2 or 3 processor with xsl:output method="xhtml"; but you will need to put any JavaScript into an external file to prevent the issue with < being serialized as &lt; as https://www.w3.org/TR/xhtml1/#C_4 states: "Use external scripts if your script uses < or & or ]]> or --".

In the end, in most cases you have it way easier if your text/html HTML elements are in no namespace.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.