XPATH содержит (строка, строка) не работает - PullRequest
1 голос
/ 10 октября 2010

s У меня есть XML-файл, который выглядит следующим образом ...

<a>
  <b>
    <version>1.0</version>
    <c>
       <Module>foo.EXE</Module>
    </c>
    <c>
       <Module>bar.DLL</Module>
    </c>
  </b>
</a>

У меня есть COM DLL, которая использует объекты MSXML2: IXMLDOMNode, которые вызывают "selectNodes" что-то вроде ...

    CComPtr<MSXML2::IXMLDOMNodeList> oRes = NULL ;
    HRESULT hResult = m_StartNode->selectNodes(sQuery, &oRes) ;

Когда sQuery равен //a/b/c[Module[contains(.,'EXE')]], тогда hResult равен E_FAIL и :: GetLastError () возвращает 0.

Конечно, я новичок в XPATH, но почему бы не вернуть все элементы 'c', в которых есть элемент Module, содержащий 'EXE'.

((редактировать)) Другие более простые выражения XPATH работают. //a/b/c например, возвращает все элементы, как ожидалось. Похоже, что когда я использую 'contains ()' или 'end-with ()', XPATH дает сбой.

Вот полное консольное приложение, демонстрирующее проблему.

// XMLTest.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#import <msxml3.dll> raw_interfaces_only rename("value", "xmlvalue")

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitialize(NULL);
    CComPtr<MSXML2::IXMLDOMDocument> thedoc;
    thedoc.CoCreateInstance(__uuidof(MSXML2::DOMDocument));
    _variant_t filename(L"c:\\shared\\test\\BlackListSmall.xml");
    VARIANT_BOOL success;
    HRESULT res = thedoc->load(filename, &success);
    _bstr_t sQuery = L"//a/b/c[Module[contains(.,'EXE')]]";
    CComPtr<MSXML2::IXMLDOMNodeList> oRes;
    thedoc->selectNodes(sQuery, &oRes);
    thedoc = NULL;
    oRes = NULL;
    CoUninitialize();
    return 0;
}

и это содержимое stdafx.h

#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#ifndef STRICT
#define STRICT
#endif
#define _ATL_APARTMENT_THREADED
#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS  // some CString constructors will be explicit
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
using namespace ATL;

Кстати, когда я запускаю это и получаю вызов selectNodes (), я получаю три сообщения в окне вывода отладчика ...

First-chance exception at 0x7564fbae in XMLTest.exe: 0xE0000001: 0xe0000001.
First-chance exception at 0x7564fbae in XMLTest.exe: 0xE0000001: 0xe0000001.
First-chance exception at 0x7564fbae in XMLTest.exe: 0xE0000001: 0xe0000001.

... и стек вызовов не предоставляет никакой реальной информации, когда я разбиваю все исключения.

((Окончательное редактирование)) Я вручил ответ Димитру, см. Ниже. Вот изменения, которые я внес в свою примерную программу в соответствии с его ответом ...

#import <msxml4.dll> raw_interfaces_only rename("value", "xmlvalue")
...
CComPtr<MSXML2::IXMLDOMDocument2> thedoc; //changed from IXMLDOMDocument
...
HRESULT res = thedoc->load(filename, &success);    // unchanged
_bstr_t lang = L"SelectionLanguage";  // inserted 
_variant_t xpathlang = L"XPath";      // inserted
thedoc->setProperty(lang,xpathlang);  // inserted
_bstr_t sQuery = L"//a/b/c[Module[contains(.,'EXE')]]";  //unchanged
...

Еще раз спасибо, Димитр

Ответы [ 2 ]

1 голос
/ 10 октября 2010

Необходимо выполнить это для объекта документа :

setProperty("SelectionLanguage", "XPath");

перед вызовом метода SelectNodes() с выражениями XPath.

Значение по умолчанию неXPath, но какой-то более ранний язык выбора.

0 голосов
/ 10 октября 2010

Вы хотите:

"//a/b/c[contains(./Module/text(),'EXE')]"

Предполагается, что вы хотите, чтобы элементы c имели дочерний элемент Module, имеющий текст, содержащий строку 'EXE'

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...