MSXML選択ノードが機能しない
-
08-07-2019 - |
質問
私は自動化されたテストアプリに取り組んでおり、現在は同一であるはずの2つの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>
要素があることに注意してください。)
2つのドキュメントの<value>
タグを抽出し、それらの値を比較したいです。私はその方法を知っています。問題は抽出そのものです。
C ++にこだわっているため、MSXMLを使用し、データ形式を変更することになった場合に備えて、アプリが実際のXML操作を抽象化できるようにするラッパーを作成しました。
そのラッパーであるCSimpleXMLParserは、XMLドキュメントをロードし、その<!> quot; top record <!> quot;を設定します。 XMLドキュメントのドキュメント要素に。 (CRecordは、そのサブクラスの1つであるCXMLRecordを持つ抽象クラスであり、子レコードへの単独またはグループによるアクセスを許可し、レコードの<!> quot; value <!> quot;へのアクセスも許可します(子要素の値またはCXMLRecordの場合は属性。 / p>
私のコードでは、次のことを行います(すべての<report>
ノードが返されるかどうかを確認するだけです):
CSimpleXMLParser parserReportData;
parserReportData.OpenXMLDocument(strPathToXML);
bool bGetChildrenSuccess = parserReportData.GetFirstRecord()->GetChildRecords(listpChildren, _T("subreport"));
これは常にfalseを返します。 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));
}
実行すると、最上位レコードがMSXML::IXMLDOMNodeListPtr
要素に確実に正しく設定されます。子ノード(ラッパーではなく、MSXMLインターフェイスを介して)や名前などを取得するなど、あらゆる種類のことを行うことができます。 XML構成ファイルを解析するためのアプリ内の他の場所で、問題なく動作します。
XPathクエリ式に何か問題があるのではないかと考えましたが、考えられるすべての順列に喜びはありません。このXMLファイルを処理しようとすると、IXMLDOMNodePtr::SelectNodes()
によって返される<=>の長さは常に0です。
これは私を夢中にさせます。
解決
.NETのXmlDocumentオブジェクトを使用してこれを行うことに慣れていますが、効果はここで同じだと思います:
XMLドキュメントに名前空間(名前のないものも含む)が含まれている場合、Xpathクエリでも名前空間を使用する必要があります。そのため、名前空間をXMLDoumentに追加する必要があります。これは、コードに名前を付け、XPATHクエリにプレフィックスを含める必要があります(プレフィックスがxmlドキュメントと名前空間がそれを整理する限り、xpath)
SO、/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
他のヒント
ノードを選択しているときに名前空間への参照が表示されません。これが根本的な問題になると思います。