синтаксический анализ XML — метод C ++ Arabica (более Xerces-c) getNodeValue () не возвращает фактическое значение

Я использую обертку Arabica поверх Xerces-c для разбора XML. Пример кода ниже возвращает правильные имена при использовании метода .getNodeName (), но не правильное значение при использовании метода .getNodeValue ():

bool readXML(bfs::path xmlfullfile)
{
// first check to see if the file exists
if (!bfs::is_regular_file(xmlfullfile)) return false;

Arabica::SAX2DOM::Parser<std::string> domParser;
Arabica::SAX::CatchErrorHandler<std::string> eh;
Arabica::DOM::Document<std::string> xmlDoc;
Arabica::SAX::InputSource<std::string> is;

domParser.setErrorHandler(eh);
is.setSystemId(xmlfullfile.string());
domParser.parse(is);

if(!eh.errorsReported())
{
xmlDoc = domParser.getDocument();
xmlDoc.normalize();

Arabica::DOM::NodeList<string_type> objects = xmlDoc.getElementsByTagName("object");
for (size_t t = 0; t < objects.getLength(); t++)
{
Arabica::DOM::Node<std::string> object = objects.item(t);
Arabica::DOM::NodeList<std::string> values = object.getChildNodes();
for (size_t u = 0; u < values.getLength(); u++)
{
values.item(u).normalize();
string name = values.item(u).getNodeName();
string val = values.item(u).getNodeValue();
cout << "Node streaming = \"" << values.item(u) << "\", meaning that name = \"" << name << "\" and value = \"" << val << "\"" << endl;
}
}
return true;
} else {
std::cerr << eh.errors() << std::endl;
eh.reset();
return false;
}
}

Пример XML, который я пытаюсь проанализировать:

<annotation>
<filename>1a.jpg</filename>
<folder>Sample</folder>
<source>
<database>Some database</database>
<annotation>Annotator</annotation>
<image>Some source</image>
</source>
<size>
<width>3264</width>
<height>1840</height>
<depth>0</depth>
</size>
<segmented>0</segmented>
<object>
<name>somename</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<occluded>0</occluded>
<bndbox>
<xmin>48</xmin>
<ymin>671</ymin>
<xmax>3213</xmax>
<ymax>1616</ymax>
</bndbox>
</object>
</annotation>

Вывод выглядит примерно так:

Node streaming = "", meaning that name = "#text" and value = ""Node streaming = "<name>somename</name>", meaning that name = "name" and value = ""Node streaming = "", meaning that name = "#text" and value = ""Node streaming = "<pose>Unspecified</pose>", meaning that name = "pose" and valu
e = ""Node streaming = "", meaning that name = "#text" and value = ""Node streaming = "<truncated>0</truncated>", meaning that name = "truncated" and
value = ""Node streaming = "", meaning that name = "#text" and value = ""Node streaming = "<difficult>0</difficult>", meaning that name = "difficult" and
value = ""Node streaming = "", meaning that name = "#text" and value = ""Node streaming = "<occluded>0</occluded>", meaning that name = "occluded" and va
lue = ""Node streaming = "", meaning that name = "#text" and value = ""Node streaming = "<bndbox>
<xmin>48</xmin>
<ymin>671</ymin>
<xmax>3213</xmax>
<ymax>1616</ymax>
</bndbox>", meaning that name = "bndbox" and value = ""Node streaming = "", meaning that name = "#text" and value = ""

Не совсем уверен, что я делаю не так. Так как getNodeName () возвращает правильное имя (если, конечно, это не #text), тот факт, что getNodeValue () ничего не возвращает, заставляет меня задуматься.

1

Решение

Вы учитываете только пробелы и текстовые узлы.
Добавление DTD, которое не допускает текстовые узлы в этом месте, может быть полезным.
Не проверяющий парсер должен сообщать обо всех узлах пробелов,
и не допускается делать предположения о том, что является игнорируемым, а что нет.

Итог, если вы хотите избавиться от текстовых узлов пробелов,
вам придется запрограммировать это самостоятельно в своей программе DOM

1

Другие решения

Я нашел решение после сравнения моего кода с некоторыми другими библиотеками XML. Очевидно, что значение узла не является простым текстовым полем, и нужно получить первого потомка этого простого конечного узла, чтобы иметь возможность доступа к текстовому значению. Не уверен, что способ, которым я это делаю, является лучшим, но вот код на тот случай, если у кого-то есть такая же проблема:

for (size_t u = 0; u < values.getLength(); u++)
{
string name = values.item(u).getNodeName();
if (name == "#text") continue;
string val = values.item(u).getFirstChild().getNodeValue();
cout << "Node streaming = \"" << values.item(u) << "\", meaning that name = \"" << name << "\" and value = \"" << val << "\"" << endl;
}

Примечание. Рабочий код должен учитывать тот факт, что не все узлы являются простыми конечными узлами. Так что мой код — это только половина решения.

0

По вопросам рекламы [email protected]