Olaf said:
Hm, shouldn't there be a cursor then, or is it just in some proto state?
XMLTOCURSOR() seems to follow these three steps, in case there is no schema or a target cursor in place:
[ol 1]
[li]MSXML.Load the document[/li]
[li]Go through the nodes tree and build a mapping from XML elements to VFP columns, including the determination of the data type of the columns[/li]
[li]Go through the nodes tree again, and fetch the contents from the XML nodes into the VFP columns[/li]
[/ol]
If something goes wrong with step 3, VFP will create a cursor, nevertheless, and will fill with as many rows it's able to import without error.
That is, this will create a cursor with RECCOUNT() = 0
Code:
Local lcXML
CLEAR
USE IN SELECT("crsFromXMLfails")
Text To lcXML NoShow
<?xml version="1.0" encoding="Windows-1252" standalone="yes"?>
<VFPData>
<tablename>
<fieldname>.</fieldname>
</tablename>
</VFPData>
EndText
On Error ? Message(), "in Line", Lineno()
XMLToCursor(lcXML,"crsFromXMLfails")
ON ERROR
BROWSE
So will this (the import finishes at the first error):
Code:
Local lcXML
CLEAR
USE IN SELECT("crsFromXMLfails")
Text To lcXML NoShow
<?xml version="1.0" encoding="Windows-1252" standalone="yes"?>
<VFPData>
<tablename>
<fieldname>.</fieldname>
</tablename>
<tablename>
<fieldname>0</fieldname>
</tablename>
</VFPData>
EndText
On Error ? Message(), "in Line", Lineno()
XMLToCursor(lcXML,"crsFromXMLfails")
ON ERROR
BROWSE
But if the dot value comes after some other valid numeric values, the RECCOUNT() will reflect the number of rows validly imported (in this case, RECCOUNT() = 1):
Code:
Local lcXML
CLEAR
USE IN SELECT("crsFromXMLfails")
Text To lcXML NoShow
<?xml version="1.0" encoding="Windows-1252" standalone="yes"?>
<VFPData>
<tablename>
<fieldname>0</fieldname>
</tablename>
<tablename>
<fieldname>.</fieldname>
</tablename>
</VFPData>
EndText
On Error ? Message(), "in Line", Lineno()
XMLToCursor(lcXML,"crsFromXMLfails")
ON ERROR
BROWSE
On its own, XMLTOCURSOR() is a great function to quickly import data from an XML document into a VFP cursor for inspection, but, because of the decisions it takes on column mapping, I never use it in production code without a previously prepared schema or cursor.
For instance, in the following example, the imported data maybe not exactly what we would (or could) expect:
Code:
Local lcXML
CLEAR
USE IN SELECT("crsFromXMLfails")
Text To lcXML NoShow
<?xml version="1.0" encoding="Windows-1252" standalone="yes"?>
<VFPData>
<tablename>
<fieldname>0</fieldname>
<other>2020-02-30</other>
</tablename>
<tablename>
<fieldname>1</fieldname>
<other>2020-12-00</other>
</tablename>
</VFPData>
EndText
On Error ? Message(), "in Line", Lineno()
XMLToCursor(lcXML,"crsFromXMLfails")
ON ERROR
BROWSE