Работа с XML файлами через MSXML версии 6.0

Для работы с MSXML версии 6.0 в сборке Xml предназначены классы DOMDocument60 и FreeThreadedDOMDocument60. В «Форсайт. Аналитическая платформа» и начиная с Prognoz Platform версии 8.0 работа со всеми XML файлами осуществляется через MSXML версии 6.0 (изменено наследование классов DOMDocument, DOMDocument40 и FreeThreadedDOMDocument), поэтому имеющийся код приложения может перестать работать. Это связано с изменением алгоритма работы системных функций в плане учета пространств имен XML-файла. Например, имеется исходный файл «Data.xml» со следующим содержимым:

<?xml version="1.0" encoding="utf-8"?>

<root xmlns="http://www.w3.org/1999/xhtml">

  <items>

    <item>A</item>

    <item>B</item>

    <item>C</item>

  </items>

</root>

Для работы с данным файлом использовался следующий код:

Sub LoadXML;
Var
    XMLDoc: IXMLDOMDocument;
    XMLName: String = "c:\Data.xml";
    Loaded: Boolean;
    Nodes: IXmlDomNodeList;
Begin
    XMLDoc := New DOMDocument.Create;
    Loaded := XMLDoc.load(XMLName);
    //...
    If Loaded Then
        //Получение вершин
        Nodes := XMLDOc.documentElement.childNodes;
        Debug.WriteLine(Nodes.length);
        Nodes := XMLDOc.getElementsByTagName("root"); //Получить элемент root
        Debug.WriteLine(Nodes.length);
        Nodes := XMLDOc.getElementsByTagName("items"); //Получить элемент items
        Debug.WriteLine(Nodes.length);
        Nodes := XMLDOc.getElementsByTagName("item"); //Получить все элементы item
        Debug.WriteLine(Nodes.length);
    End If;
End Sub LoadXML;

При работе через MSXML 3.0 данный код вернул бы соответственно 1, 1 и 3 вершины. После перехода на продукт «Форсайт. Аналитическая платформа» или Prognoz Platform версии 8.0 и выше для выполнения данного кода будет использоваться MSXML 6.0 и код вернет следующие значения: 1, 0, 0. Метод getElementsByTagName не распознает пространство имен по умолчанию и поэтому не найдет указанные элементы. Для решения проблемы необходимо убрать пространство имен по умолчанию или задать для него какой-либо префикс:

<?xml version="1.0" encoding="utf-8"?>

<root xmlns:ns="http://www.w3.org/1999/xhtml">

  <items>

    <item>A</item>

    <item>B</item>

    <item>C</item>

  </items>

</root>

Указанный выше способ подходит если имеется возможность изменить используемый XML-файл. Если такой возможности нет, то можно воспользоваться программным способом введения пространства имен с префиксом. Более подробно данный способ описан в MSDN: https://support.microsoft.com/ru-ru/kb/313372. В Fore необходимый метод setProperty, который используется для задания внутреннего свойства SelectionNamespaces, доступен в интерфейсе IXMLDOMDocument2. Код приложения при этом изменится следующим способом:

Sub LoadXML;
Var
    XMLDoc: IXMLDOMDocument2;
    XMLName: String = "c:\Data.xml";
    Loaded: Boolean;
    Nodes: IXmlDomNodeList;
Begin
    XMLDoc := New DOMDocument.Create;
    XMLDoc.setProperty("SelectionNamespaces""xmlns:ns=""http://www.w3.org/1999/xhtml""");
    Loaded := XMLDoc.load(XMLName);
    //...
    If Loaded Then
        //Получение вершин, дочерних для корневой вершины
        Nodes := XMLDOc.documentElement.childNodes;
        Debug.WriteLine(Nodes.length);
        Nodes := XMLDOc.selectNodes("ns:root"); //Получить элемент root
        Debug.WriteLine(Nodes.length);
        Nodes := XMLDOc.selectNodes("//ns:items"); //Получить элемент items
        Debug.WriteLine(Nodes.length);
        Nodes := XMLDOc.selectNodes("//ns:item"); //Получить все элементы item
        Debug.WriteLine(Nodes.length);
    End If;
End Sub LoadXML;

См. также:

Сборка XML | Примеры работы с XML-файлами