Re: LoadXML, RespectNesting by MichelRoy
MichelRoy
Fri Dec 02 22:42:03 CST 2005
personnaly, i use a simple xml parser that converts the xml document to an
object
if you have simple xml files without schemas but with nested relashionship
it is simple enough to use. sometimes, if someone else build the xml doc, it
may not fit
foxpro's requirement. field names... as long as you can read the document,
you can recreate tables and relationships.
ex:
ii=xml2obj("orders.xml","ORDER,ORDER_LINE") && nest on order and order-line
FOR EACH oOrder IN ii.Root.Order
WITH oOrder.Order_header
? .confirmation.value
WITH .billing_info
? .billing_name.value, .billing_city.value, .billing_state.value,
.billing_zip.value
ENDWITH
ENDWITH
FOR EACH oOrderLine IN oOrder.Order_line
WITH oOrderLine
? .sku.value, .descr.value, .qty, .price
ENDWITH
NEXT
NEXT
the xml doc is like this.
<?xml version="1.0" encoding="Windows-1252"?>
<root>
<ORDER>
<ORDER-HEADER>
<CONFIRMATION>32</CONFIRMATION>
<ORDER-CURRENCY>USD</ORDER-CURRENCY>
<ORDER-CONTACT>JOE BLOE></ORDER-CONTACT>
<PO-NUMBER>7340260271</PO-NUMBER>
<ORDER-DATE>20051027</ORDER-DATE>
<FREIGHT>
<FREIGHT-AMOUNT>10</FREIGHT-AMOUNT>
<FREIGHT-COMPANY>UPS></FREIGHT-COMPANY>
<FREIGHT-ACCOUNT>U100</FREIGHT-ACCOUNT>
</FREIGHT>
<BILLING-INFO>
<BILLING-ACCOUNT>U0257</BILLING-ACCOUNT>
<BILLING-NAME>JR EWING HOLDINGS</BILLING-NAME>
<BILLING-CONTACT>SOMEONE</BILLING-CONTACT>
<BILLING-ADDRESS1>806 ROSALIA DR.</BILLING-ADDRESS1>
<BILLING-ADDRESS2></BILLING-ADDRESS2>
<BILLING-CITY>FT LAUDERDALE</BILLING-CITY>
<BILLING-STATE>FL</BILLING-STATE>
<BILLING-COUNTRY>USA</BILLING-COUNTRY>
<BILLING-ZIP>32771</BILLING-ZIP>
</BILLING-INFO>
<SHIPPING-INFO>
<SHIPPING-ACCOUNT>BIGMALL</SHIPPING-ACCOUNT>
<SHIPPING-NAME>JR EWING #100 THE BIG MALL</SHIPPING-NAME>
<SHIPPING-CONTACT></SHIPPING-CONTACT>
<SHIPPING-ADDRESS1>THE ACME COMPANY</SHIPPING-ADDRESS1>
<SHIPPING-ADDRESS2>400 WOODBRIDGE RD</SHIPPING-ADDRESS2>
<SHIPPING-CITY>LONGWOOD</SHIPPING-CITY>
<SHIPPING-STATE>FL</SHIPPING-STATE>
<SHIPPING-COUNTRY>USA</SHIPPING-COUNTRY>
<SHIPPING-ZIP>32779</SHIPPING-ZIP>
</SHIPPING-INFO>
<SPINSTR>Please make sure this order goes to the store instead of my
house</SPINSTR>
</ORDER-HEADER>
<ORDER-LINE QTY="1" PRICE="66.00">
<sku>012345678905</sku>
<descr>white t-shirt</descr>
</ORDER-LINE>
<ORDER-LINE QTY="1" PRICE="66.00">
<sku>012346678905</sku>
<descr>blue t-shirt</descr>
</ORDER-LINE>
</ORDER>
</root>
the xml2obj parser :
PROCEDURE XML2Obj(lcFile AS STRING, lcArr AS string, liFlags AS Integer)
PRIVATE paNames
IF EMPTY(lcArr)
lcArr = ""
ENDIF
DIMENSION paNames(1)
= ALINES(paNames, lcArr, .t., ",")
oXML = CREATEOBJECT("Msxml2.DOMDocument")
IF VARTYPE(liFlags) = "N" AND liFlags = 1
oXML.LOADXML(lcFile)
ELSE
oXML.LOAD(lcfile)
ENDIF
loObj = Processnode(oXML,0, CREATEOBJECT("EMPTY"))
RETURN loObj.DOC
ENDPROC
PROCEDURE Processnode(ox AS OBJECT, lvl AS INTEGER, oVfp AS OBJECT)
LOCAL lonode AS OBJECT, lcnodename AS STRING
IF ox.nodetype = 3 OR ox.nodetype = 4
ADDPROPERTY(oVfp,"VALUE",ox.nodevalue)
ELSE
lcnodename = STRTRAN(ox.Nodename,"-","_")
IF ":"$lcnodename
lcNodename = STREXTRACT(lcNodename,":","",1,2)
ENDIF
IF lcnodename = "#document"
lcnodename = "Doc"
ENDIF
ISARRAY = .F.
FOR J = 1 TO ALEN(paNames)
IF UPPER(ALLTRIM(panames(j))) == UPPER(ALLTRIM(lcNodeName))
ISARRAY = .T.
IF NOT PEMSTATUS(oVfp,lcNodeName,5)
Addproperty(oVfp,lcNodeName, CREATEOBJECT("Collection"))
ENDIF
WITH EVALUATE("oVfp."+lcNodeName)
.add(CREATEOBJECT("EMPTY"))
lcnodename = lcnodename + ".ITEM("+TRANSFORM(.COUNT)+")"
ENDWITH
ENDIF
NEXT
IF NOT ISARRAY
ADDPROPERTY(oVfp,lcnodename,CREATEOBJECT("EMPTY"))
ENDIF
IF VARTYPE(ox.ATTRIBUTES) = "O"
FOR i = 0 TO ox.ATTRIBUTES.LENGTH - 1
lcAttName = STRTRAN(ox.ATTRIBUTES.ITEM(i).Nodename,"-","_")
IF ":"$lcattname
lcattname = STREXTRACT(lcattname,":","",1,2)
ENDIF
ADDPROPERTY(EVALUATE("ovfp."+lcnodename), lcAttName,
ox.ATTRIBUTES.ITEM(i).nodevalue)
NEXT
ENDIF
ENDIF
IF ox.haschildnodes
lonode = ox.firstchild
Processnode(lonode,lvl+1,EVALUATE("ovfp."+lcnodename))
LOCAL lonext AS OBJECT
lonext = lonode.NEXTSIBLING
DO WHILE NOT ISNULL(lonext)
Processnode(lonext,lvl+1,EVALUATE("ovfp."+lcnodename))
lonext = lonext.NEXTSIBLING
ENDDO
ELSE
IF NOT ISNULL(ox.Attributes) AND ox.Attributes.Length = 0
ADDPROPERTY(EVALUATE("ovfp."+lcnodename),"VALUE","") && empty values
ENDIF
ENDIF
RETURN oVfp
ENDPROC
"drsystems@gmail.com" wrote:
> I read that chapter before posting this.
>
> Two things:
> 1) It seems that the schema that VFP9 is creating from the cursors I
> use is not reflecting the relationships between the cursors
> (parent-child).
>
> 2) I don't understand why we need to specify primary, and foreign keys
> for nested XML It seems to completely defeat the purpose of using XML
> as an external datasource to parse.
>
>