gpt4 book ai didi

c++ - MSXML 选择节点不工作

转载 作者:太空狗 更新时间:2023-10-29 20:32:55 26 4
gpt4 key购买 nike

我正在开发一个自动化测试应用程序,目前正在编写一个函数来比较两个 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 接口(interface),而不是通过我的包装器)或其名称等。我知道我的包装器可以工作,因为我使用它在应用程序的其他地方用于解析 XML 配置文件,并且可以完美地工作。

我想也许我在 XPath 查询表达式上做错了什么,但我能想到的每一种排列都没有带来任何乐趣。 MSXML::IXMLDOMNodeListPtrIXMLDOMNodePtr::SelectNodes() 返回当我尝试处理此 XML 文件时,它的长度始终为 0。

这让我发疯。

最佳答案

我习惯用 .NET 的 XmlDocument 对象这样做,但我认为这里的效果是一样的:

如果 XML 文档包含命名空间——即使是未命名的——那么 Xpath 查询也必须使用一个。因此,您必须将命名空间添加到 XMLDoument 中,您不妨在代码中为其命名,并在 XPATH 查询中包含前缀(xml 文档和 xml 文档之间的前缀不同并不重要) xpath,只要 namespace 将其整理出来)

所以,当您使用像 /report/subreport/record/field/value 这样的 XPath 时,您实际上需要先设置文档的命名空间:

  pXMLDoc->setProperty(_bstr_t("SelectionNamespaces"),
_bstr_t("xmlns:r="http://www.**.com/**"));

然后 selectNodes() 使用 /r:report/r:subreport/r:record/r:field/r:value

关于c++ - MSXML 选择节点不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/284716/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com