質問

私は自動化されたテストアプリに取り組んでおり、現在は同一であるはずの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

他のヒント

ノードを選択しているときに名前空間への参照が表示されません。これが根本的な問題になると思います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top