To work with MSXML 6.0, the Xml assembly has the DOMDocument60 and FreeThreadedDOMDocument60 classes. Starting with Prognoz Platform 8.0 working with all XML files is done via MSXML 6.0 (inheritance of the DOMDocument, DOMDocument40 and FreeThreadedDOMDocument classes is changed), that is why the current application code may not work properly. This is caused by change in working algorithm of system functions in the aspect of consideration of XML file namespaces. For example, there is the source file Data.xml with that contain the following:
<?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>
The following code was used to work with this file:
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
//Get nodes
Nodes := XMLDOc.documentElement.childNodes;
Debug.WriteLine(Nodes.length);
Nodes := XMLDOc.getElementsByTagName("root"); //Get the "root" element
Debug.WriteLine(Nodes.length);
Nodes := XMLDOc.getElementsByTagName("items"); //Get the "items" element
Debug.WriteLine(Nodes.length);
Nodes := XMLDOc.getElementsByTagName("item"); //Get all "item" elements
Debug.WriteLine(Nodes.length);
End If;
End Sub LoadXML;
On working via MSXML 3.0 this code would returns 1, 1 and 3 nodes, respectively. After updating to Prognoz Platform 8.0 or later, MSXML 6.0 is used to execute this code, and the code returns the following values: 1, 0, 0. The getElementsByTagName method does not recognizes default namespace that is why cannot find the specified elements. To solve the issue, remove the default namespace or set some prefix for it:
<?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>
The above specified method is relevant if it is available to edit the XML file in use. If there is not such possibility, it is available to use the program method of entering namespace with prefix. For more details about this method see in the MSDN: https://support.microsoft.com/ru-ru/kb/313372. In the Fore the setProperty required method used to set the SelectionNamespaces internal property is available in the IXMLDOMDocument2 interface. Application code is changed in the following way:
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
//Getting children of the root node
Nodes := XMLDOc.documentElement.childNodes;
Debug.WriteLine(Nodes.length);
Nodes := XMLDOc.selectNodes("ns:root"); //Get root element
Debug.WriteLine(Nodes.length);
Nodes := XMLDOc.selectNodes("//ns:items"); //Get items element
Debug.WriteLine(Nodes.length);
Nodes := XMLDOc.selectNodes("//ns:item"); //Get all item elements
Debug.WriteLine(Nodes.length);
End If;
End Sub LoadXML;
See also: