似乎所有主流浏览器都实现DOMParser API,以便可以将XML解析为DOM,然后使用XPath,getElementsByTagName等查询...
但是,检测解析错误似乎更棘手. DOMParser.prototype.parseFromString始终返回有效的DOM.当发生解析错误时,返回的DOM包含一个<parsererror>元素,但在每个主要浏览器中它略有不同.
示例JavaScript:
xmlText = '<root xmlns="http://default" xmlns:other="http://other"><child><otherr:grandchild/></child></root>';
parser = new DOMParser();
dom = parser.parseFromString(xmlText, 'text/xml');
console.log((new XMLSerializer()).serializeToString(dom));
Run Code Online (Sandbox Code Playgroud)
Opera中的结果:
DOM的根是一个<parsererror>元素.
<?xml version="1.0"?><parsererror xmlns="http://www.mozilla.org/newlayout/xml/parsererror.xml">Error<sourcetext>Unknown source</sourcetext></parsererror>
Run Code Online (Sandbox Code Playgroud)
Firefox中的结果:
DOM的根是一个<parsererror>元素.
<?xml-stylesheet href="chrome://global/locale/intl.css" type="text/css"?>
<parsererror xmlns="http://www.mozilla.org/newlayout/xml/parsererror.xml">XML Parsing Error: prefix not bound to a namespace
Location: http://fiddle.jshell.net/_display/
Line Number 1, Column 64:<sourcetext><root xmlns="http://default" xmlns:other="http://other"><child><otherr:grandchild/></child></root>
---------------------------------------------------------------^</sourcetext></parsererror>
Run Code Online (Sandbox Code Playgroud)
Safari中的结果:
该<root>元素正确分析,但包含嵌套<parsererror>在不同的命名空间比Opera和Firefox的<parsererror>元素.
<root xmlns="http://default" xmlns:other="http://other"><parsererror xmlns="http://www.w3.org/1999/xhtml" style="display: block; white-space: pre; border: 2px solid #c77; padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color: black"><h3>This page contains the following errors:</h3><div style="font-family:monospace;font-size:12px">error on line 1 at column 50: Namespace prefix otherr on grandchild is not defined
</div><h3>Below is a rendering of the page up to the first error.</h3></parsererror><child><otherr:grandchild/></child></root>
Run Code Online (Sandbox Code Playgroud)
我是否缺少一种简单的跨浏览器方式来检测XML文档中是否出现解析错误?或者我必须查询<parsererror>不同浏览器可能生成的每个可能元素的DOM 吗?
csp*_*ode 18
这是我提出的最佳解决方案.
我尝试解析故意无效的XML字符串并观察结果<parsererror>元素的命名空间.然后,在解析实际的XML时,我可以getElementsByTagNameNS用来检测相同类型的<parsererror>元素并抛出一个Javascript Error.
// My function that parses a string into an XML DOM, throwing an Error if XML parsing fails
function parseXml(xmlString) {
var parser = new DOMParser();
// attempt to parse the passed-in xml
var dom = parser.parseFromString(xmlString, 'text/xml');
if(isParseError(dom)) {
throw new Error('Error parsing XML');
}
return dom;
}
function isParseError(parsedDocument) {
// parser and parsererrorNS could be cached on startup for efficiency
var parser = new DOMParser(),
errorneousParse = parser.parseFromString('<', 'text/xml'),
parsererrorNS = errorneousParse.getElementsByTagName("parsererror")[0].namespaceURI;
if (parsererrorNS === 'http://www.w3.org/1999/xhtml') {
// In PhantomJS the parseerror element doesn't seem to have a special namespace, so we are just guessing here :(
return parsedDocument.getElementsByTagName("parsererror").length > 0;
}
return parsedDocument.getElementsByTagNameNS(parsererrorNS, 'parsererror').length > 0;
};
Run Code Online (Sandbox Code Playgroud)
请注意,此解决方案不包括Internet Explorer所需的特殊外壳.但是,IE中的事情要简单得多.使用一种loadXML方法解析XML ,如果解析成功或失败,则分别返回true或false.有关示例,请参见http://www.w3schools.com/xml/xml_parser.asp.
Ras*_*ast 13
当我第一次来到这里时,我赞成原始答案(通过cspotcode),然而,它在Firefox中不起作用.由于生成的文档的结构,生成的命名空间始终为"null".我做了一些研究(在这里查看代码).这个想法是不使用
invalidXml.childNodes[0].namespaceURI
Run Code Online (Sandbox Code Playgroud)
但
invalidXml.getElementsByTagName("parsererror")[0].namespaceURI
Run Code Online (Sandbox Code Playgroud)
然后在原始答案中按名称空间选择"parsererror"元素.但是,如果您有一个有效的XML文档,其<parsererror>标记位于浏览器使用的相同名称空间中,则最终会出现误报.所以,这是一个启发式方法来检查你的XML是否成功解析:
function tryParseXML(xmlString) {
var parser = new DOMParser();
var parsererrorNS = parser.parseFromString('INVALID', 'text/xml').getElementsByTagName("parsererror")[0].namespaceURI;
var dom = parser.parseFromString(xmlString, 'text/xml');
if(dom.getElementsByTagNameNS(parsererrorNS, 'parsererror').length > 0) {
throw new Error('Error parsing XML');
}
return dom;
}
Run Code Online (Sandbox Code Playgroud)
为什么不在DOMParser中实现异常?
有趣的事情在当前的上下文中值得一提:如果你试图获取XML文件XMLHttpRequest,解析的DOM将存储在responseXML属性中,或者null,如果XML文件内容无效.不是例外,不是parsererror或另一个具体指标.只是null.
2022 年回到这个问题,该方法的文档DOMParser.parseFromString()提供了一个更简单的解决方案:
const parser = new DOMParser();
const xmlString = "<warning>Beware of the missing closing tag";
const doc = parser.parseFromString(xmlString, "application/xml");
const errorNode = doc.querySelector('parsererror');
if (errorNode) {
// parsing failed
} else {
// parsing succeeded
}
Run Code Online (Sandbox Code Playgroud)
虽然接受的答案对我有用,但使用该Document.querySelector()方法确实要简单得多,因为您不必确定namespaceURI元素的parsererror。