如何从 HTML 文档 (Xerces/Xqilla) 中提取带有 XPath 2 的节点
How can I extract a node with XPath 2 from a HTML document (Xerces/Xqilla)
我想使用 xerces 和 xqilla 库从带有 XPATH2 的 html 文档中提取特定节点,但显然我无法构建有效的 XPATH 表达式,或者我的代码某处有误。
我当前的代码:
#include <iostream>
#include <string>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMImplementationRegistry.hpp>
#include <xercesc/dom/DOMConfiguration.hpp>
#include <xercesc/dom/DOMXPathExpression.hpp>
#include <xercesc/dom/DOMXPathResult.hpp>
#include <xercesc/dom/DOMLSParser.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMLSSerializer.hpp>
#include <xercesc/dom/DOMLSOutput.hpp>
#include <xercesc/sax/SAXParseException.hpp>
#include <xercesc/sax/ErrorHandler.hpp>
#include <xercesc/framework/StdOutFormatTarget.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xqilla/xqilla-dom3.hpp>
#include <xercesc/parsers/AbstractDOMParser.hpp>
using namespace std;
const char document[] = { 0x3c, 0x21, 0x44, 0x4f, 0x43, ....., 0x6c, 0x3e, 0x0a, 0x00 };
int main() {
// init xerces and xqilla engines
XQillaPlatformUtils::initialize();
// retrieve xqilla DOMImpl.
xercesc::DOMImplementation* xqilla_impl
= xercesc::DOMImplementationRegistry::getDOMImplementation(X("XPath2 3.0"));
{
// create DOMLSParser
AutoRelease<xercesc::DOMLSParser> parser(xqilla_impl->createLSParser(xercesc::DOMImplementationLS::MODE_SYNCHRONOUS, 0));
xercesc::DOMConfiguration *config = parser->getDomConfig();
config->setParameter(xercesc::XMLUni::fgXercesScannerName, xercesc::XMLUni::fgWFXMLScanner);
// retrieve lesson page:
string str(document);
xercesc::Wrapper4InputSource* wrapper =
new xercesc::Wrapper4InputSource(
new xercesc::MemBufInputSource((XMLByte*) str.c_str(), (XMLSize_t) str.length(), "index.html", false));
// create DOM structure:
xercesc::DOMDocument* dom = parser->parse(wrapper);
AutoRelease<xercesc::DOMXPathExpression> expression(
dom->createExpression(xercesc::XMLString::transcode("html/head"), 0)
);
AutoRelease<xercesc::DOMXPathResult> result(expression->evaluate(
dom, xercesc::DOMXPathResult::ITERATOR_RESULT_TYPE, 0
));
cout << result->iterateNext() << endl; // output is always 0
}
XQillaPlatformUtils::terminate();
return 0;
}
我需要更改什么?
编辑:
我想查看的 HTML 文件是一大堆文件,所以我制作了一个小示例文件来测试我的程序 and/or XPATH 表达式:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Some title</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="title" content="Some title" />
<meta name="keywords" content="Keywords" />
<meta name="description" content="A short description" />
</head>
<body>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy <b>eirmod <u>tempor</u> invidunt ut</b> labore et dolore<br />
magna aliquyam erat, sed diam voluptua. At vero eos et accusam
et justo duo dolores et ea rebum. Stet clita kasd gubergren,<br />
no sea takimata sanctus est Lorem ipsum dolor sit amet.
</p>
</body>
</html>
即使这样,我的程序也没有找到任何具有我的 XPATH 表达式的节点。
我能够为我的问题找到 2 个次优解决方案
- 1.解决方案:
使用不关心的 XPath 表达式
像 '*:html/*:head/*:title/text()'. 这样的命名空间
- 2。解决方案:
在解析器中关闭 DOM 个命名空间:
配置->setParameter(xercesc::XMLUni::fgDOMNamespaces, false);
如果我找到了一种为未命名的 DOM 命名空间手动设置自定义前缀的方法,或者如果我有一个 XPath 表达式,我可以在其中明确指定一个空前缀,我会更高兴,但现在至少我可以处理我的文件。
html
和 head
元素在命名空间中,而您的 XPath 正在寻找没有命名空间的元素。使用 "h:html/h:head"
并将 "h"
前缀绑定到 XHTML 命名空间。我不知道如何与 XQilla 进行绑定 API,但会有一些方法可以做到这一点。
我想使用 xerces 和 xqilla 库从带有 XPATH2 的 html 文档中提取特定节点,但显然我无法构建有效的 XPATH 表达式,或者我的代码某处有误。
我当前的代码:
#include <iostream>
#include <string>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMImplementationRegistry.hpp>
#include <xercesc/dom/DOMConfiguration.hpp>
#include <xercesc/dom/DOMXPathExpression.hpp>
#include <xercesc/dom/DOMXPathResult.hpp>
#include <xercesc/dom/DOMLSParser.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMLSSerializer.hpp>
#include <xercesc/dom/DOMLSOutput.hpp>
#include <xercesc/sax/SAXParseException.hpp>
#include <xercesc/sax/ErrorHandler.hpp>
#include <xercesc/framework/StdOutFormatTarget.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xqilla/xqilla-dom3.hpp>
#include <xercesc/parsers/AbstractDOMParser.hpp>
using namespace std;
const char document[] = { 0x3c, 0x21, 0x44, 0x4f, 0x43, ....., 0x6c, 0x3e, 0x0a, 0x00 };
int main() {
// init xerces and xqilla engines
XQillaPlatformUtils::initialize();
// retrieve xqilla DOMImpl.
xercesc::DOMImplementation* xqilla_impl
= xercesc::DOMImplementationRegistry::getDOMImplementation(X("XPath2 3.0"));
{
// create DOMLSParser
AutoRelease<xercesc::DOMLSParser> parser(xqilla_impl->createLSParser(xercesc::DOMImplementationLS::MODE_SYNCHRONOUS, 0));
xercesc::DOMConfiguration *config = parser->getDomConfig();
config->setParameter(xercesc::XMLUni::fgXercesScannerName, xercesc::XMLUni::fgWFXMLScanner);
// retrieve lesson page:
string str(document);
xercesc::Wrapper4InputSource* wrapper =
new xercesc::Wrapper4InputSource(
new xercesc::MemBufInputSource((XMLByte*) str.c_str(), (XMLSize_t) str.length(), "index.html", false));
// create DOM structure:
xercesc::DOMDocument* dom = parser->parse(wrapper);
AutoRelease<xercesc::DOMXPathExpression> expression(
dom->createExpression(xercesc::XMLString::transcode("html/head"), 0)
);
AutoRelease<xercesc::DOMXPathResult> result(expression->evaluate(
dom, xercesc::DOMXPathResult::ITERATOR_RESULT_TYPE, 0
));
cout << result->iterateNext() << endl; // output is always 0
}
XQillaPlatformUtils::terminate();
return 0;
}
我需要更改什么?
编辑:
我想查看的 HTML 文件是一大堆文件,所以我制作了一个小示例文件来测试我的程序 and/or XPATH 表达式:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Some title</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="title" content="Some title" />
<meta name="keywords" content="Keywords" />
<meta name="description" content="A short description" />
</head>
<body>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy <b>eirmod <u>tempor</u> invidunt ut</b> labore et dolore<br />
magna aliquyam erat, sed diam voluptua. At vero eos et accusam
et justo duo dolores et ea rebum. Stet clita kasd gubergren,<br />
no sea takimata sanctus est Lorem ipsum dolor sit amet.
</p>
</body>
</html>
即使这样,我的程序也没有找到任何具有我的 XPATH 表达式的节点。
我能够为我的问题找到 2 个次优解决方案
- 1.解决方案:
使用不关心的 XPath 表达式 像 '*:html/*:head/*:title/text()'. 这样的命名空间
- 2。解决方案:
在解析器中关闭 DOM 个命名空间:
配置->setParameter(xercesc::XMLUni::fgDOMNamespaces, false);
如果我找到了一种为未命名的 DOM 命名空间手动设置自定义前缀的方法,或者如果我有一个 XPath 表达式,我可以在其中明确指定一个空前缀,我会更高兴,但现在至少我可以处理我的文件。
html
和 head
元素在命名空间中,而您的 XPath 正在寻找没有命名空间的元素。使用 "h:html/h:head"
并将 "h"
前缀绑定到 XHTML 命名空间。我不知道如何与 XQilla 进行绑定 API,但会有一些方法可以做到这一点。