Domanda

Sto lavorando a un'app di test automatizzata e attualmente sto scrivendo una funzione che confronta i valori tra due file XML che dovrebbero essere identici, ma potrebbero non esserlo. Ecco un esempio dell'XML che sto tentando di elaborare:

<?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>

(Nota potrebbero esserci più <subreport> elementi e all'interno di questi, più <record> elementi.)

Quello che mi piacerebbe è estrarre i tag <value> di due documenti e poi confrontare i loro valori. Quella parte che so fare. Il problema è l'estrazione stessa.

Dato che sono bloccato in C ++, sto usando MSXML e ho scritto un wrapper per consentire alla mia app di sottrarre la manipolazione XML effettiva, nel caso in cui decida di cambiare il formato dei miei dati.

Quel wrapper, CSimpleXMLParser, carica un documento XML e imposta il suo " top record " all'elemento documento del documento XML. (CRecord è una classe astratta con CXMLRecord una delle sue sottoclassi e che dà accesso ai record figlio singolarmente o per gruppo e consente anche l'accesso al & Quot; valore & Quot; del Record (valori per elementi child o attributi, nel caso di CXMLRecord.) Un CXMLRecord contiene un MSXML :: MSXMLDOMNodePtr e un puntatore a un'istanza di CSimpleXMLParser.) Il wrapper contiene anche funzioni di utilità per restituire i figli, che CXMLRecord utilizza per restituire i propri record figlio.

Nel mio codice, faccio quanto segue (cercando di restituire tutti i <report> nodi solo per vedere se funziona):

CSimpleXMLParser parserReportData;
parserReportData.OpenXMLDocument(strPathToXML);
bool bGetChildrenSuccess = parserReportData.GetFirstRecord()->GetChildRecords(listpChildren, _T("subreport"));

Questo restituisce sempre false. Il fondamento dell'implementazione di CXMLRecord :: GetChildRecords () è sostanzialmente

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;

E CSimpleXMLParser :: SelectNodes () è:

MSXML2::IXMLDOMNodeListPtr CSimpleXMLParser::SelectNodes(LPCTSTR strXPathFilter, MSXML2::IXMLDOMNodePtr pXMLNode)
{
    return pXMLNode->selectNodes(_bstr_t(strXPathFilter));
}

Quando eseguito, il record più alto viene sicuramente impostato correttamente sull'elemento MSXML::IXMLDOMNodeListPtr. Posso fare ogni sorta di cose con esso, come ottenere i suoi nodi figlio (attraverso l'interfaccia MSXML, non tramite il mio wrapper) o il suo nome, ecc. So che il mio wrapper può funzionare, perché uso altrove nell'app per l'analisi di un file di configurazione XML e funziona perfettamente.

Pensavo che forse stavo facendo qualcosa di sbagliato nell'espressione della query XPath, ma ogni permutazione a cui potevo pensare non dà gioia. Il IXMLDOMNodePtr::SelectNodes() restituito da <=> è sempre di lunghezza 0 quando provo a gestire questo file XML.

Questo mi sta facendo impazzire.

È stato utile?

Soluzione

Sono abituato a farlo con gli oggetti XmlDocument di .NET, ma penso che l'effetto sia lo stesso qui:

Se il documento XML include uno spazio dei nomi - anche uno senza nome - anche la query Xpath deve usarne uno. Quindi, dovrai aggiungere lo spazio dei nomi a XMLDoument a cui potresti anche dare un nome nel codice e includere il prefisso nella query XPATH (non importa che i prefissi siano diversi tra il documento XML e xpath, purché gli spazi dei nomi lo riordinino)

SO, mentre usi XPath come /report/subreport/record/field/value, devi prima impostare lo spazio dei nomi del tuo documento:

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

e quindi selectNodes() usando /r:report/r:subreport/r:record/r:field/r:value

Altri suggerimenti

Non vedo alcun riferimento a uno spazio dei nomi quando si selezionano i nodi. Mi aspetto che questo sia il problema fondamentale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top