1

我需要一种方法来包含不包含全局打开/关闭标记/元素的分段 XML。该片段正在增长,因为程序不时向其中附加数据(更多块),因此它既没有结束标记也没有开始标记。我已经将 !DOCTYPE 与 !ENTITY 一起使用,但这已被弃用,并且新的 Xinclude 似乎没有办法导入它,因为它强制片段具有“一个”开始和结束标记。

更多信息:以下内容适用于 IE-10,但不适用于 IE-11。后者不导入文件current.log

注意:根据此网站,Microsoft Edge 不支持它:https ://docs.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>

日志current.log如下所示:

<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>
4

1 回答 1

0

根据您的评论,我了解您使用 IE 11 直接从文件系统加载 XML 文档。我认为 IE 已默认使用 MSXML 6 而不是 MSXML 3,默认情况下 XSLT 和 MSXML 6 禁止 DTD 并且不加载外部实体. 我知道的唯一规避方法是将 MSXML 6 与脚本一起使用并设置它必须允许 DTD、加载外部资源的属性(对于您的情况,因为 DTD 仅用于加载外部实体,以禁用验证):

<?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>

那样的话,如果输入的文件test201706070101.xml有内容

<?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>

在 IE 11 中加载并启用脚本,则解析完整日志,例如第二个文档具有

<?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>

并且样式表已经发布,IE窗口中的输出是

Test


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

所以外部实体已经加载。主要缺点显然是需要脚本,另一个缺点是使用的带有 MSXML 和 ActiveXObject 的脚本与 Edge 不兼容,因为它不支持 ActiveXObject。

我发布这个答案作为一个建议,如果您想依赖 IE 进行 XSLT 转换,可能会有帮助,从长远来看,将 XSLT 到 HTML 转换移动到像 .NET 这样的平台可能会更好,您可以在其中更好地控制 XML 解析的方式和 XSLT 处理交互。

示例文件位于https://martin-honnen.github.io/xslt/2017/test201706070101.xml、https://martin-honnen.github.io/xslt/2017/test201706070102.xmlhttps :// martin -honnen.github.io/xslt/2017/test2017060701.xsl虽然我知道您想在本地而不是通过 HTTP(S) 执行此操作。

于 2017-06-07T16:43:41.657 回答