1

I need a way to include a fragmented XML not containing a global opening/closing tag/element. The fragment is growing because a program is appending data (more blocks) into it from time to time, so it neither going to have an ending tag nor an starting tag. I have used !DOCTYPE with a !ENTITY but this is being deprecated and the new Xinclude does not seem to have a way to import it as it forces the fragment to have "one" opening and closing tag.

More info: The following works fine with IE-10 but it does not work in IE-11. The latter does not import the file current.log.

Note: Microsoft Edge does not support it according to this web site: https://learn.microsoft.com/en-us/internet-explorer/ie11-deploy-guide/deprecated-document-modes

<?xml version='1.0' encoding='ISO-8859-1'?>
<?xml-stylesheet type='text/xsl' href='IndexLog.xsl'?>

<!DOCTYPE myRoot [<!ENTITY thisMonthLog SYSTEM "current.log">]>

<myRoot>
    &thisMonthLog;
</myRoot>

the log current.log looks like this:

<block>
   <a>any text</a>
   <b>any text</b>
   <c>any text</c>
   <d>any text</d>
   <e>any text</e>
</block>
<block>
   <a>any text</a>
   <b>any text</b>
   <c>any text</c>
   <d>any text</d>
   <e>any text</e>
</block>
Guasqueño
  • 405
  • 9
  • 20
  • What you describe is not a well-formed XML document, because an XML document has exactly one root element. You probably will need to look to non-XML tools to work with it -- or at least to convert it into well-formed XML as a first step. – John Bollinger Jun 01 '17 at 18:40
  • 1
    Where do you find `DOCTYPE` being deprecated? – Martin Honnen Jun 01 '17 at 19:49
  • 1
    And what is your programming platform or API? For instance the Microsoft .NET framework with https://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings.conformancelevel(v=vs.110).aspx and the `Fragment` setting allows you to build an `XPathDocument` as the input to `XslCompiledTransform` that is a fragment without a single root element. – Martin Honnen Jun 01 '17 at 20:06
  • This MS web site says "Edge" does not support it any more: https://learn.microsoft.com/en-us/internet-explorer/ie11-deploy-guide/deprecated-document-modes – Guasqueño Jun 02 '17 at 15:07
  • Regarding platform, the XML file is to be opened with Internet Explorer 11, the style sheet will transform it to HTML and present it as nice table in IE. – Guasqueño Jun 02 '17 at 19:03
  • If the problem is about IE and/or Edge you might want to add tags specific to them. Microsoft has never supported XInclude I think, I am not sure what their options are if IE 11 and/or Edge don't support external entities any more, other than obviously doing the transformation outside the browser, as for instance with .NET as indicated in a previous comment. – Martin Honnen Jun 07 '17 at 14:11
  • Can you please clarify in your example what the name of the file that has the two functions (runXslt and runXslt) would be? Where that script goes? – Guasqueño Jun 10 '17 at 14:31

1 Answers1

0

Based on your comments I understand you load an XML document from the file system directly with IE 11. I think IE has moved to use MSXML 6 instead of MSXML 3 by default for XSLT and MSXML 6 by default prohibits DTDs and does not load external entities. The only way I know to circumvent that is to use MSXML 6 with script and to set the properties it has to allow DTDs, load external resources (and for your case, as the DTD is only used to load an external entity, to disable validation):

<?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="/">
        <html>
            <head>
                <title>Test</title>
                <script>
                    function runXslt(xmlUri, xsltUri, targetElement) {
                      var xmlDoc = new ActiveXObject('Msxml2.DOMDocument.6.0');
                      xmlDoc.async = false;
                      xmlDoc.resolveExternals = true;
                      xmlDoc.validateOnParse = false;
                      xmlDoc.setProperty('ProhibitDTD', false);
                      xmlDoc.load(xmlUri);

                      var xsltDoc = new ActiveXObject('Msxml2.DOMDocument.6.0');
                      xsltDoc.async = false;
                      xsltDoc.load(xsltUri);

                      targetElement.insertAdjacentHTML('beforeEnd', xmlDoc.documentElement.transformNode(xsltDoc));
                    }
                </script>
                <script>
                    document.addEventListener(
                      'DOMContentLoaded',
                      function() {
                        runXslt('test201706070101.xml', 'test2017060701.xsl', document.body);
                      },
                      false
                    );
                </script>
            </head>
            <body>
                <h1>Test</h1>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="myRoot">
        <section>
            <h2>Content</h2>
            <xsl:apply-templates/>
        </section>  
    </xsl:template>

    <xsl:template match="block">
        <ul>
            <xsl:apply-templates/>
        </ul>
    </xsl:template>

    <xsl:template match="block/*">
        <li>
            <xsl:apply-templates/>
        </li>
    </xsl:template>

</xsl:stylesheet>

That way, if the input document test201706070101.xml with the content

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test2017060701.xsl"?>
<!DOCTYPE myRoot [
  <!ENTITY thisMonthLog SYSTEM "test201706070102.xml">
]>
<myRoot>
    &thisMonthLog;
</myRoot>

is loaded in IE 11 and scripting is enabled, the full log is parsed, e.g. with the second document having

<?xml version="1.0" encoding="UTF-8"?>
<block>
    <a>any text</a>
    <b>any text</b>
    <c>any text</c>
    <d>any text</d>
    <e>any text</e>
</block>
<block>
    <a>any text</a>
    <b>any text</b>
    <c>any text</c>
    <d>any text</d>
    <e>any text</e>
</block>

and the stylesheet being as already posted, the output in the IE window is

Test


Content
•any text
•any text
•any text
•any text
•any text
•any text
•any text
•any text
•any text
•any text

so the external entity has been loaded. Major drawback is obviously that script is needed, another drawback is that the used script with MSXML and ActiveXObject is not compatible with Edge as that doesn't support ActiveXObject.

I post that answer as a suggestion on what might help if you want to rely on IE for XSLT transformation, in the long end it might be better to move the XSLT to HTML transformation to a platform like .NET where you better control how XML parsing and XSLT processing interact.

Example files are online at https://martin-honnen.github.io/xslt/2017/test201706070101.xml, https://martin-honnen.github.io/xslt/2017/test201706070102.xml and https://martin-honnen.github.io/xslt/2017/test2017060701.xsl although I understand you want to do that locally and not over HTTP(S).

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • Yes, I need to do that locally and not over HTTP(S). Thanks. – Guasqueño Jun 10 '17 at 14:41
  • Can you please clarify in your example what the name of the file that has the two functions (runXslt and runXslt) would be? So I can understand how it goes with the others. – Guasqueño Jun 10 '17 at 14:44
  • @Guasqueño, as you can see, I have added links to three sample files, the script code is simply put as a result element into the XSLT code, so the idea is to have the XML reference the XSLT stylesheet as before, however, instead of transforming the complete XML directly, instead the resulting HTML with script reloads the XML, now with the right settings to make sure the external entity is resolved and loaded, and then transforms the rest of the XML, putting the result into the HTML using `insertAdjacentHTML`. – Martin Honnen Jun 10 '17 at 15:00
  • Got it, the name of the first file is the one ending on 0701.xsl. I was a little confused for the naming convention and the fact that the script was referencing back the files that called the script, which means that the XSL script content depend on the name of the files that uses it. This means that at the beginning of each month, in addition to creating the two log files, I have to also automatically create the xsl that work with them. You solution work, thanks. **It is a complex work around the limitations of the standard not supporting a built-in solution for this problem.** – Guasqueño Jun 16 '17 at 18:30
  • Thank you Martin this helped me. I was trying to disable the DTD prohibition using VB in ASP classic, and the setProperty, resolveExternals, and validateOnParse attributes seemed to do the trick! – Dave Sep 08 '17 at 14:34