【发布时间】:2018-09-28 20:06:59
【问题描述】:
我正在使用 libxml2 从 XML 文件中解析特定标签(例如标题)。
解析这个 XML:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<entry>
<title type="html">Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs1</title>
</entry>
<entry>
<title type="html">Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs2</title>
</entry>
<entry>
<title type="html">Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs3</title>
</entry>
<entry>
<title type="html">Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs4</title>
</entry>
<entry>
<title type="html">Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs5</title>
</entry>
<entry>
<title type="html">Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs6</title>
</entry>
<entry>
<title type="html">Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs7</title>
</entry>
<entry>
<title type="html">Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs8</title>
</entry>
<entry>
<title type="html">Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs9</title>
</entry>
<entry>
<title type="html">Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs10</title>
</entry>
</feed>
使用这个 C++ 代码
void CXMLManager::processNode(xmlTextReaderPtr reader)
{
static bool root = true;
std::string name;
name = std::string((const char *) xmlTextReaderConstName (reader));
if (name == "entry")
{
if (root)
{
m_name = m_title;
root = false;
return;
}
static bool closeEntry = true;
if (closeEntry)
{
m_feedBuffer.push_back( CFeed { m_name, m_title, m_updated, m_author, m_link } );
m_title = "";
}
closeEntry = !closeEntry;
}
else if (name == "title" && xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT)
{
m_title = getElementContent(reader);
std::cout << "Title: " << m_title << std::endl;
}
}
std::string CXMLManager::getElementContent(xmlTextReaderPtr reader)
{
xmlNodePtr node = xmlTextReaderCurrentNode(reader);
xmlChar* text = xmlNodeGetContent(node);
return std::string((const char *) text);
}
void CXMLManager::streamFile(const char *data, size_t size)
{
xmlTextReaderPtr reader;
int ret;
/*
* Pass some special parsing options to activate DTD attribute defaulting,
* entities substitution and DTD validation
*/
reader = xmlReaderForMemory(data, size, NULL, NULL,
XML_PARSE_DTDATTR | /* default DTD attributes */
XML_PARSE_NOENT); /* substitute entities */
if (reader != NULL)
{
ret = xmlTextReaderRead(reader);
while (ret == 1)
{
processNode(reader);
ret = xmlTextReaderRead(reader);
}
}
else
{
throw CFeedreaderException("FEEDREADER: Failed to parse XML.", E_WRONG_XML);
}
}
在大多数情况下,我得到了正确的结果,但一次一次——我得到了空字符串(甚至认为它在 XML 中是正确的):
Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs1
Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs2
Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs3
Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs4
Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs6
Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs7
Swedish ISP spanked for sexist 'distracted boyfriend' advert for developer jobs8
在解析之前我已经检查了很多次 XML 并且它是正确的,所以我不知道这里可能是什么问题。此输入会定期丢失第 5 个字符串。
【问题讨论】:
-
我已经使用 libxml2 多年了,从来没有遇到过这样的问题。但我不太使用阅读器 API。您能否提供一个minimal reproducible example(强调Complete)准确显示您是如何循环遍历元素的,以及EXACT xml?此外,在
return std::move(std::string((const char *) text));上,您有内存泄漏,因为您必须在xmlNodeGetContent()返回的指针上调用xmlFree()。您应该改用xmlTextReaderValue()(也需要xmlFree())或xmlTextReaderConstValue()(不需要)。此外,std::move()是多余的。 -
@RemyLebeau 感谢您指出错误。我已经用原始代码和 XML 更新了我的问题。
-
你还在泄漏
xmlNodeGetContent()分配的内存。您还泄露了reader本身