Logo

Hacker’s Guide to Visual FoxPro
An irreverent look at how Visual FoxPro really works. Tells you the inside scoop on every command, function, property, event and method of Visual FoxPro.

CURSORTOXML(), XMLTOCURSOR()

As their names imply, these functions convert cursors to XML data and back. These functions were added in VFP 7.

Usage

nBytesWritten = CursorToXML( nWorkArea | cAlias, cDestination
    [, nOutputFormat [, nFlags [, nRecords [, cSchemaName
    [, cSchemaLocation [, cNameSpace ] ] ] ] ] ] )

Parameter

Value

Meaning

nWorkArea

Numeric

Convert the data from the table in the specified work area.

cAlias

Character

Convert the data from the table open with the specified alias.

cDestination

Character

The file name or the name of the variable to send the XML to. If nFlags is set to output to a memory variable that doesn't exist, the variable is created. Specifying "Output.XML" here means you need to include 512 in nFlags to prevent the error "Object OUTPUT is not found."

nOutputFormat

1 (Default)

Create element-centric output. This is the kind that's compatible with VS.NET.

2

Create attribute-centric output.

3

Create unformatted, attribute-centric output.

nFlags

Note: the nFlags values are additive.

0 (Default)

Generate Unicode (UTF-8) formatted XML. This is the "pretty" version you'll want to look at for troubleshooting, but it's a little bulkier to transmit.

1

Generate an unformatted, continuous-string XML. Much more compact to send, but not "pretty" to look at.

2

Include empty elements in the following notation: "<element></element>"

4

Preserve white space in fields.

8

Wrap memo fields in CDATA sections to ensure the parser doesn't fail because it evaluates data that may contain illegal characters.

16

Set output encoding to the code page of cursor. If output encoding is omitted, US Windows (1252) is used.

32

Set output encoding to UTF-8 without character translation. (UTF-8 is a compressed form of Unicode, and a superset of ASCII.)

48

Set output encoding to UTF-8, translating character data to UTF-8.

512

Output to a file. If omitted, the XML is sent to a memory variable.

4096

Disables base64 encoding. Use this if you are exporting memo fields. In VFP, base64 encoding is intended to encode only binary data, not character memo fields.

nRecords

Numeric

First nRecords to write to XML. To limit the fields, use SET FIELDS TO, or convert a cursor you SELECT from the original source.

Omitted, 0 or number greater than the number of records in the table

Convert all records to XML.

cSchemaName

Empty string or omitted

No schema is produced.

"1"

Produce an inline schema.

Character

A file name to store the schema. If this is a URI (Universal Resource Identifier, of which URLs are a subset), the external schema is written to the same location as the XML file, and must be uploaded to the server.

cSchemaLocation

Character

An optional parameter that tells where the schema file is. This can be an HTTP address or other URI. Use this parameter only if the destination of the schema is not in the same location as the XML data.

cNameSpace

Empty string or omitted

No namespace declaration is written to an external schema; for an inline schema, the targetNameSpace attribute is set to the empty string.

Character

Set the targetNamespace attribute to the specified value, and set the elementFormDefault attribute to "qualified."

nBytesWritten

Numeric

Number of bytes of XML written.

CURSORTOXML() takes a cursor and makes an XML string, either in a memory variable or written to a file. It has a lot of parameters that can lead to a lot of complexity. Fortunately, much of what you’re likely to need to do doesn’t have to be complex.

We could write a book on formatting an XML string, and how to use it. If you’re serious about XML, you’ll need more than a few pages, or even a chapter to understand it. We suggest you find a good book or Web site on XML to find out more about XML.

If you are working with code pages, you should refer to the updates in VFP’s ReadMe.HTM file. Several last-minute changes were made regarding which code pages are supported.

The schema implementation is based on the W3C Recommendation of April 4, 2001. Any changes to the W3C recommendation since then (for example, the revisions of September 2001) are not reflected in the schemas generated by CursorToXML().

Keep up with the service packs, as this is one area that is scheduled for enhancements.

Huh? A fixed bug in a function that just entered the language? Yep, the VFP team in Redmond was quick to bring us SP1 for VFP 7, which fixed a number of issues with the XML implementation, among other things. Specifically for CursorToXML(), two things were fixed.

The first fix is when nFlags includes the value 8, which wraps memo fields in CDATA blocks. One would assume that no data translation would take place, meaning that the phrase "<attribute>" is not translated to "&gtattribute&lt". VFP 7.0 improperly translates the data; SP1 fixes this error.

The second fix is that in VFP 7.0, when the schema attribute is written, it is written as lsDataSet (a lower case "L" instead of an upper case "I"). SP1 fixes this problem.

Example

USE _SAMPLES + "data\customer.dbf" IN 0 SHARED
* Creates an element-centric file that preserves white space:
nBytes = CursorToXML("Customer", "Customer.xml", 1, 4+512)

* Creates a variable with an element-centric file.
x = CursorToXML("Customer", "cXMLstring", 1)

Usage

nRecords = XMLToCursor( eXMLSource [ , cCursorName
           [ , nFlags ] ] )

Parameter

Value

Meaning

eXMLSource

VFP variable or VFP memo field or
XML file name or
HTTP request or
SOAP method call or
ADO stream or equivalent character expression

The source of the XML data.

cCursorName

Empty string or omitted

The results go to a cursor called XMLRESULT.

Character

The name of the cursor in which to place the results.

nFlags

Note: the nFlags values are additive.

512

Treat the eXMLSource parameter as an XML data file name.

1024

Create character and memo fields using the NOCPTRANS option.

2048

If an imported XSD schema has a decimal data type where totalDigits="19" and fractionDigits = "4", convert this data type to currency in the resulting cursor.

4096

Disable base64 decoding.

8192

Indicates that the table/cursor referenced in cCursorName already exists. The data is appended to the table/cursor if data already exists. If cCursorName is blank, the current work area is assumed; if cCursorName is not found, an error occurs.

The element names are mapped to field names in cCursorName. At least one element must match, but no error is generated if cCursorName doesn't contain columns for all of the elements defined in the XML file, or has additional columns. "Data type mismatch" errors occur if the data types defined in the XML file are incompatible with the cursor/table.

nRecords

Numeric

The number of records created.

XMLTOCURSOR() has fewer parameters than its companion, CURSORTOXML(). It should have fewer; all the information needed to create a cursor is contained in the XML file!

In the initial shipping version of VFP 7, there was some disagreement within the FoxPro documentation as to exactly what the nFlag parameter values can be. The IntelliSense Quick Info feature shows values from 0–3. The Help file shows values of 4, 512, and 1024. (The ReadMe.HTM file also lists 2048 and 4096). The Help and the accompanying ReadMe.HTM files are correct. SP1 has a script to correct the FoxCode table; see the ReadMe file for more information.

The FoxPro team is working hard to keep the XML features up-to-date as the various technologies move from technology previews into full-blown specifications. You’ll want to keep abreast of the Hot Fixes and Service Patches available at the Microsoft Web site for updates to XML related functions.

Here are terrific examples of why you want to keep up with the Hot Fixes and Service Patches. These items are fixed in SP1:

Visual Studio writes out date/time data to XML files with fractional seconds and time zones—for example, 2002-10-05T00:00:00.0000000-07:00. VFP 7.0 cannot convert this, and therefore uses an empty date. SP1 reads this properly.

VFP 7.0 crashes with a C0000005 error if a root attribute is not found. The root attribute is sometimes called "<root>", but it can be called anything as long as there's a beginning tag after the declaration line (which also must be present) and a matching ending tag at the end of the document. (VFP's CursorToXML() function writes the root attribute as "<VFPData>".) SP1 no longer crashes, but does properly fail if there is not a well-formed XML document.

If there are large numbers of columns in the XML document, somewhere around the 150-column range, VFP 7.0 gets cranky. You either get a syntax error or a C0000005 fatal error, whichever VFP randomly selects. VFP 7 SP1 handles large numbers of columns properly.

If the XML file has an inline schema, you get an extra record in VFP 7.0 (but it works fine if you use an external schema or no schema). SP1 fixes this, too.

And finally, SP1 fixes a problem with reading XML from double-byte character systems. The length of the data field is half of what it should be (the number of characters, not the number of bytes needed to represent those characters). As a result, the data was truncated. It's fixed now.

Example

* Converts a file to a cursor.
nRowsWritten = XMLToCursor("test.xml", "testme", 512)

See Also

Set Fields, Set Safety, VFPXMLProgId, XMLUpdateGram()