none
MSXML, Xpath и префиксы пространства имен атрибутов. RRS feed

  • Вопрос

  • Господа, всем доброго дня!
    Помомгите осилить неясность с сабжем. Дело обстоит так.

    Необходимо средствами MSXML 4.0 сегенерировать XML документ подобного вида:

    <?xml version="1.0" encoding="utf-8"?>
    <xx:settings_root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xsi:schemaLocation="urn:xx AppSettingsSchema.xsd" 
             xmlns:xx="urn:xx">
     <xx:app_settings xx:name="TestApp_1.0">
      <xx:group xx:name="Application Settings">
       <xx:variable xx:name="First Setting">
        <xx:value xx:type="uint32">60302040</xx:value>
       </xx:variable>
       <xx:variable xx:name="Second Setting">
        <xx:value xx:type="uint32">60302040</xx:value>
       </xx:variable>
      </xx:group>
     </xx:app_settings>
    </xx:settings_root>


    Псевдокод, не претендующий на правильность, но создающий вышеописанный документ таков:


     CComPtr< MSXML2::IXMLDOMDocument2 > spDoc;
    
     spDoc.CoCreateInstance( L"MSXML2.DOMDocument.4.0" );
     spDoc->setProperty( CComBSTR( L"NewParser" ), CComVariant( true ) );
     spDoc->setProperty( CComBSTR( L"SelectionLanguage" ), CComVariant( L"XPath" ) );
     spDoc->setProperty( CComBSTR( L"SelectionNamespaces" ), CComVariant( "xmlns:xx='urn:xx'" ) );
    
     CComPtr< MSXML2::IXMLDOMProcessingInstruction > spVersion;
     CComPtr< MSXML2::IXMLDOMNode > spInsertedVersion, spSettingsRoot, spInsertedRoot;
     CComPtr< MSXML2::IXMLDOMElement > spElem;
    
     spDoc->createProcessingInstruction( CComBSTR( L"xml" ), CComBSTR( L"version=\"1.0\" encoding=\"utf-8\"" ), &spVersion );
     spDoc->appendChild( spVersion, &spInsertedVersion );
     spDoc->createNode( CComVariant( NODE_ELEMENT ), CComBSTR( L"xx:settings_root" ), CComBSTR( L"urn:xx" ), &spSettingsRoot );
     spDoc->appendChild( spSettingsRoot, &spInsertedRoot );
    
     spElem = spInsertedRoot
     spElem->setAttribute( CComBSTR( L"xmlns:xsi" ), CComVariant( L"http://www.w3.org/2001/XMLSchema-instance" ) )
     spElem->setAttribute( CComBSTR( L"xsi:schemaLocation" ), CComVariant( L"urn:xx AppSettingsSchema.xsd" ) )


    Процедура создания листовых узлов настроек принимает на вход пути вида:

    "/TestApp_1.0/Application Settings/First Setting"
    "/TestApp_1.0/Application Settings/Second Setting"


    , на основе которых создется запрос XPath вида:

    "xx:settings_root/xx:app_settings[@xx:name='TestApp_1.0']/xx:group[@xx:name='Application Settings']/xx:variable[@xx:name='First Setting']/xx:value"
    "xx:settings_root/xx:app_settings[@xx:name='TestApp_1.0']/xx:group[@xx:name='Application Settings']/xx:variable[@xx:name='Second Setting']/xx:value"


    При этом до создания нода "xx:value" проверяется наличие его предков попыткой найти каждый из них по соответствующей части вышеописанных XPath запросов, например:

    "xx:settings_root/xx:app_settings[@xx:name='TestApp_1.0']/xx:group[@xx:name='Application Settings']"


    И тут возникает проблема: при созданных уже узлах из последнего примера, парсер по указанной строке ничего не находит. При этом, если у атрибута "xx:name" убрать квалификатор пространства имен "xx", поиск проходит корректно. И все бы ничего, но, если загрузить документ с уже существующими настройками и поппытаться дополнить его испрользуя тот же код, поиск БЕЗ квалификатора пространства имен "xx" работать не будет, а с ним — да.

    Буду крайне признателен и благодарен, если кто-то сможет объяснить мне в чем дело и как с этим жить.
    22 апреля 2011 г. 11:00