我需要一种方法来包含一个不包含全局开始/结束标记/元素的碎片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>
答案 0 :(得分:0)
根据您的评论,我了解您直接使用IE 11从文件系统加载XML文档。我认为IE已默认为XSLT使用MSXML 6而不是MSXML 3,默认情况下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.xml和https://martin-honnen.github.io/xslt/2017/test2017060701.xsl处于联机状态,但我知道您希望在本地而不是通过HTTP(S)执行此操作。