Я работаю над приложением автоматизированного тестирования и в настоящее время нахожусь в процессе написания функции, которая сравнивает значения между двумя файлами XML, которые должны быть идентичными, но могут не совпадать. Вот пример XML, который я пытаюсь обработать:
<?xml version="1.0" encoding="utf-8"?>
<report xmlns="http://www.**.com/**">
<subreport name="RBDReport">
<record rowNumber="1">
<field name="Time">
<value>0</value>
</field>
<field name="Reliability">
<value>1.000000</value>
</field>
<field name="Unreliability">
<value>0.000000</value>
</field>
<field name="Availability">
<value> </value>
</field>
<field name="Unavailability">
<value> </value>
</field>
<field name="Failure Rate">
<value>N/A</value>
</field>
<field name="Number of Failures">
<value> </value>
</field>
<field name="Total Downtime">
<value> </value>
</field>
</record>
(Обратите внимание, что может быть несколько <subreport>
элементов, а внутри них несколько <record>
элементов.)
Я бы хотел извлечь теги <value>
из двух документов, а затем сравнить их значения. Эту часть я знаю как сделать. Проблема в самой добыче.
Поскольку я застрял в C ++, я использую MSXML и написал оболочку, позволяющую моему приложению абстрагироваться от фактических манипуляций с XML на случай, если я когда-нибудь решу изменить свой формат данных.
Эта оболочка, CSimpleXMLParser, загружает XML-документ и устанавливает свою «верхнюю запись» в элемент документа XML-документа. (CRecord является абстрактным классом с CXMLRecord одним из его подклассов, который предоставляет доступ к дочерним записям по отдельности или по группам, а также разрешает доступ к «значению» Записи (значениям для дочерних элементов или атрибутов, в случае CXMLRecord .) CXMLRecord содержит MSXML :: MSXMLDOMNodePtr и указатель на экземпляр CSimpleXMLParser.) Оболочка также содержит служебные функции для возврата дочерних элементов, которые CXMLRecord использует для возврата своих дочерних записей.
В своем коде я делаю следующее (пытаясь вернуть все <subreport>
узлы, просто чтобы посмотреть, работает ли он):
CSimpleXMLParser parserReportData;
parserReportData.OpenXMLDocument(strPathToXML);
bool bGetChildrenSuccess = parserReportData.GetFirstRecord()->GetChildRecords(listpChildren, _T("subreport"));
Это всегда возвращает ложь. Основная реализация CXMLRecord :: GetChildRecords () в основном
MSXML2::IXMLDOMNodeListPtr pListChildren = m_pParser->SelectNodes(strPath, m_pXMLNode);
if (pListChildren->Getlength() == 0)
{
return false;
}
for (long l = 0; l < pListChildren->Getlength(); ++l)
{
listRecords.push_back(new CXMLRecord(pListChildren->Getitem(l), m_pParser));
}
return true;
И CSimpleXMLParser :: SelectNodes ():
MSXML2::IXMLDOMNodeListPtr CSimpleXMLParser::SelectNodes(LPCTSTR strXPathFilter, MSXML2::IXMLDOMNodePtr pXMLNode)
{
return pXMLNode->selectNodes(_bstr_t(strXPathFilter));
}
При запуске верхняя запись определенно устанавливается на элемент <report>
правильно. Я могу делать с ним все что угодно, например получать его дочерние узлы (через интерфейс MSXML, а не через мою оболочку) или его имя и т. Д. Я знаю, что моя оболочка может работать, потому что я ее использую в другом месте приложения для анализа файла конфигурации XML, и это работает безупречно.
Я подумал, что, может быть, я что-то неправильно делал с выражением запроса XPath, но каждая перестановка, о которой я мог подумать, не доставляет радости. MSXML::IXMLDOMNodeListPtr
, возвращаемое IXMLDOMNodePtr::SelectNodes()
, всегда имеет длину 0, когда я пытаюсь разобраться с этим XML-файлом.
Это сводит меня с ума.