在 HTML5 中注入自定义元素,然后使用 XPath 检索其值返回空白
Injecting a custom element in HTML5 then retrieving its value using XPath comes back blank
我正在注入从 Web 服务生成的 XML 字符串,然后尝试使用 XPath 通过以下代码查询属性值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>tox-js</title>
</head>
<body>
<script>
//
// -----------------------------------------------
// tox element
class Tox extends HTMLElement
{
constructor(url)
{
super();
fetch(url)
.then((response)=>
{
console.log("status: "+response.status);
return response.text();
})
.then((text)=>
{
console.log("text: "+text);
try
{
var dp = new DOMParser();
var xmlDOM = dp.parseFromString(text, "text/xml");
this.appendChild(xmlDOM.documentElement);
return true;
}
catch(err)
{
console.log("err: "+err.message);
return false;
}
})
.then((ok)=>
{
if (ok)
{
try
{
var xpe = new XPathEvaluator();
var txt = xpe.evaluate("//tox-js/example/@timestamp",document,null,XPathResult.STRING_TYPE,null);
console.log("//tox-js/example/@timestamp: "+txt.stringValue);
txt = xpe.evaluate("//tox-js/example/@feedback",document,null,XPathResult.STRING_TYPE,null);
console.log("//tox-js/example/@feedback: "+txt.stringValue);
}
catch(err)
{
console.log("err: "+err.message);
}
}
else
console.log("not ok");
}
);
}
}
//
// -----------------------------------------------
// register our element with the DOM
customElements.define('tox-js',Tox);
//
// -----------------------------------------------
// create an instance and add it to the body
document.body.appendChild(new Tox('http://localhost:8080/tox/example.test.formatted?in_mask=YYYYMMDD'));
// -----------------------------------------------
//
</script>
</body>
</html>
结果注入了自定义元素。
<html lang="en">
<head>...</head>
<body>
<script>...</script>
<tox-js>
<example timestamp="20180103142036" feedback="ok">20190103</example>
</tox-js>
</body>
<html>
控制台日志确认 return 状态和 XML,但 XPath 的结果为空。
[Log] status: 200 (toxElement3.html, line 20)
[Log] text: <example timestamp="20190103142036" feedback="ok">20190103</example> (toxElement3.html, line 25)
[Log] //tox-js/example/@timestamp: (toxElement3.html, line 47)
[Log] //tox-js/example/@feedback: (toxElement3.html, line 49)
我哪里做错了?这应该不是时间问题,因为我正在使用 .then
等待上一步。
似乎与命名空间有关。
以下 XPath 对我有用:
//tox-js/*[local-name()='example']/@timestamp
检查这个答案:
XPath Doesn't Work in Dynamic HTML-Document
你也可以使用document.createElement()
or insertAdjacentHTML()
to create element from text as described here: Creating a new DOM element from an HTML string using built-in DOM methods or Prototype
在这种情况下,您的 XPath 将按预期工作。
<html lang="en">
<head></head>
<body>
<script>
window.addEventListener('load', () => {
var text = `<example timestamp="20180103142036" feedback="ok">20190103</example>`;
var el = document.getElementsByTagName('tox-js')[0];
el.insertAdjacentHTML('afterbegin', text);
var xpe = new XPathEvaluator();
var txt = xpe.evaluate("//tox-js/example/@timestamp",document,null,XPathResult.STRING_TYPE,null);
console.log(`//tox-js/example/@timestamp: ${txt.stringValue}`);
});
</script>
<tox-js>
</tox-js>
</body>
<html>
P.S。我无法解释为什么在使用 DOMParser
时会出现问题。也许 document
和 DOMParser
有不同的命名空间。因此,如果有人有更多详细信息,请随时扩展答案。
从提供的例子...
var dp = new DOMParser();
var xmlDOM = dp.parseFromString(text, "text/xml");
this.appendChild(xmlDOM.documentElement);
...变成...
this.insertAdjacentHTML('afterbegin', text);
我正在注入从 Web 服务生成的 XML 字符串,然后尝试使用 XPath 通过以下代码查询属性值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>tox-js</title>
</head>
<body>
<script>
//
// -----------------------------------------------
// tox element
class Tox extends HTMLElement
{
constructor(url)
{
super();
fetch(url)
.then((response)=>
{
console.log("status: "+response.status);
return response.text();
})
.then((text)=>
{
console.log("text: "+text);
try
{
var dp = new DOMParser();
var xmlDOM = dp.parseFromString(text, "text/xml");
this.appendChild(xmlDOM.documentElement);
return true;
}
catch(err)
{
console.log("err: "+err.message);
return false;
}
})
.then((ok)=>
{
if (ok)
{
try
{
var xpe = new XPathEvaluator();
var txt = xpe.evaluate("//tox-js/example/@timestamp",document,null,XPathResult.STRING_TYPE,null);
console.log("//tox-js/example/@timestamp: "+txt.stringValue);
txt = xpe.evaluate("//tox-js/example/@feedback",document,null,XPathResult.STRING_TYPE,null);
console.log("//tox-js/example/@feedback: "+txt.stringValue);
}
catch(err)
{
console.log("err: "+err.message);
}
}
else
console.log("not ok");
}
);
}
}
//
// -----------------------------------------------
// register our element with the DOM
customElements.define('tox-js',Tox);
//
// -----------------------------------------------
// create an instance and add it to the body
document.body.appendChild(new Tox('http://localhost:8080/tox/example.test.formatted?in_mask=YYYYMMDD'));
// -----------------------------------------------
//
</script>
</body>
</html>
结果注入了自定义元素。
<html lang="en">
<head>...</head>
<body>
<script>...</script>
<tox-js>
<example timestamp="20180103142036" feedback="ok">20190103</example>
</tox-js>
</body>
<html>
控制台日志确认 return 状态和 XML,但 XPath 的结果为空。
[Log] status: 200 (toxElement3.html, line 20)
[Log] text: <example timestamp="20190103142036" feedback="ok">20190103</example> (toxElement3.html, line 25)
[Log] //tox-js/example/@timestamp: (toxElement3.html, line 47)
[Log] //tox-js/example/@feedback: (toxElement3.html, line 49)
我哪里做错了?这应该不是时间问题,因为我正在使用 .then
等待上一步。
似乎与命名空间有关。 以下 XPath 对我有用:
//tox-js/*[local-name()='example']/@timestamp
检查这个答案: XPath Doesn't Work in Dynamic HTML-Document
你也可以使用document.createElement()
or insertAdjacentHTML()
to create element from text as described here: Creating a new DOM element from an HTML string using built-in DOM methods or Prototype
在这种情况下,您的 XPath 将按预期工作。
<html lang="en">
<head></head>
<body>
<script>
window.addEventListener('load', () => {
var text = `<example timestamp="20180103142036" feedback="ok">20190103</example>`;
var el = document.getElementsByTagName('tox-js')[0];
el.insertAdjacentHTML('afterbegin', text);
var xpe = new XPathEvaluator();
var txt = xpe.evaluate("//tox-js/example/@timestamp",document,null,XPathResult.STRING_TYPE,null);
console.log(`//tox-js/example/@timestamp: ${txt.stringValue}`);
});
</script>
<tox-js>
</tox-js>
</body>
<html>
P.S。我无法解释为什么在使用 DOMParser
时会出现问题。也许 document
和 DOMParser
有不同的命名空间。因此,如果有人有更多详细信息,请随时扩展答案。
从提供的例子...
var dp = new DOMParser();
var xmlDOM = dp.parseFromString(text, "text/xml");
this.appendChild(xmlDOM.documentElement);
...变成...
this.insertAdjacentHTML('afterbegin', text);