baanware
21st October 2004, 11:54
Hi All,

I am trying to read an XML file, but cannot make my program identify the contents of the xml-element. I have made the script below to create a simple xml-file describing my problem. The resulting file looks as follows:

<?xml version="1.0"?>
<Supplier>
<SupplierID>123456</SupplierID>
<Name>Customer Named XXX</Name>
<Address>Address YYY</Address>
</Supplier>


The file was generated by the following sample function:

function create.xml.document( domain tcsuno i.suno,
domain tcnama i.nama,
domain tcnamc i.namc)
{
BaanDocId = xmlNewNode("Supplier") |* , XML_ELEMENT, dtdId)

retVal = xmlNewDataElement("SupplierID", strip$(shiftl$(i.suno)), BaanDocId)
retVal = xmlNewDataElement("Name", strip$(shiftl$(i.nama)), BaanDocId)
retVal = xmlNewDataElement("Address", strip$(shiftl$(i.namc)), BaanDocId)

fd = seq.open("file.xml", "w" )

retVal = xmlWritePretty(fd, BaanDocId, 0 )

retVal = seq.close(fd)

retVal = xmlDelete(BaanDocId, 0)
}


Having written the file, I try to read it, and to determine the contents of the <Name> element.

function read.xml.document()
{
long fileid
long suppliernode

string error_string(120)

string xml.data(50)

|open the xml file for reading.
fd = seq.open ("file.xml", "r" )

|parse the xml file
fileid = xmlread(fd, error_string)
seq.close(fd)

|determine the data-elements
suppliernode = xmlfindmatch("<Supplier>", fileid)
if (suppliernode <> 0 ) then
retval = xmlgetdataelement(suppliernode, "<Name>", xml.data)
retval = xmlgetdataelement(suppliernode, "Name", xml.data)
retval = xmlgetdataelement(suppliernode, "", xml.data)
endif

retval = xmldelete(fileid, 0)
}


As you can see I have tried several ways to isolate the content of the "Name" element , but none of them results in the expected value
of the result-string xml.data ( = "Customer Named XXX").

Can anyone tell me how to do?

Thanks!

FransG
21st October 2004, 16:56
Replace xmlFindMatch with xmlFindFirst...

|determine the data-elements
suppliernode = xmlFindFirst("Supplier", fileid)
if (suppliernode <> 0 ) then
retval = xmlgetdataelement(suppliernode, "Name", xml.data)
endif

There is not need to put '<' and '>' within the tagname string.

xmlFindFirst assigns the first valid node to suppliernode. Where xmlFindMatch will return an a new XML structure with matching nodes.

baanware
21st October 2004, 17:57
Hi FransG

Thanks a lot. Everything seems to work beautifully now.
...Hard to believe that something that simple could cause such problems.

Anyway, just to make the XML handling more understandable to me, I have a little additional question. Suppose that we have a multilevel structure - e.g. a BOM:

<?xml version="1.0"?>
<BillOfMaterial>
<MainItemId>123456</MainItemId>
<SubItem>
<Position>10</Position>
<Sequence>1</Sequence>
<SubItemId>23456</SubItemId>
<NetQuantity>12.0</NetQuantity>
</SubItem>
<SubItem>
<Position>10</Position>
<Sequence>1</Sequence>
<SubItemId>345678</SubItemId>
<NetQuantity>24.0</NetQuantity>
</SubItem>
</BillOfMaterial>

How would you position the first and the second occurance of "SubItem".
xmlFindFirst("SubItem", fileid)
will give you the first one, but how do I find or "activate" the following occurances?

Furthermore: If I had multiple BOM's in the same XML file would the same methodology be applicable?

Thanks!

FransG
22nd October 2004, 09:03
Hi,

If you have multiple BOMs in one xml document then you need another root node (i.e. doc).


<?xml version="1.0"?>
<doc>
<BillOfMaterial>
<MainItemId>123456</MainItemId>
<SubItem>
<Position>10</Position>
<Sequence>1</Sequence>
<SubItemId>23456</SubItemId>
<NetQuantity>12.0</NetQuantity>
</SubItem>
<SubItem>
<Position>20</Position>
<Sequence>1</Sequence>
<SubItemId>345678</SubItemId>
<NetQuantity>24.0</NetQuantity>
</SubItem>
</BillOfMaterial>
<BillOfMaterial>
<MainItemId>789012</MainItemId>
<SubItem>
<Position>10</Position>
<Sequence>1</Sequence>
<SubItemId>34567</SubItemId>
<NetQuantity>12.0</NetQuantity>
</SubItem>
<SubItem>
<Position>20</Position>
<Sequence>1</Sequence>
<SubItemId>834567</SubItemId>
<NetQuantity>24.0</NetQuantity>
</SubItem>
</BillOfMaterial>
</doc>


In this xml document there are two BOMs both with two subitems. In order to read the xml document I guess you should use something like the following code fragment:

function read.xml.document()
{
long fd
long xml.id
long bom.id
long sub.item.id
long ret.val
string error_string(120)

string xml.data1(50)
string xml.data2(50)
string xml.data3(50)
string xml.data4(50)
string xml.data5(50)

|* Open the xml file for reading.
fd = seq.open ("file.xml", "r" )

|* Parse the xml file
xml.id = xmlread(fd, error_string)
seq.close(fd)

|* First check if there is a BOM present.
bom.id = xmlFindFirst("BillOfMaterial", xml.id)
|* Loop through the BOMs in the xml document.
while bom.id <> 0
ret.val = xmlGetDataElement(bom.id, "MainItemId", xml.data1)
sub.item.id = xmlFindFirst("SubItem", bom.id)
|* Loop through the Sub Items in the BOM.
while sub.item.id <> 0
ret.val = xmlGetDataElement(sub.item.id, "SubItemId", xml.data2)
ret.val = xmlGetDataElement(sub.item.id, "Position", xml.data3)
ret.val = xmlGetDataElement(sub.item.id, "Sequence", xml.data4)
ret.val = xmlGetDataElement(sub.item.id, "NetQuantity", xml.data5)
|* Check for another component (sub item).
sub.item.id = xmlGetRightSibling(sub.item.id)
endwhile
|* Check for another BOM.
bom.id = xmlGetRightSibling(bom.id)
endwhile

ret.val = xmlDelete(xml.id, 0)
}


I haven't tested the code, but I think you get an idea about it.

baanware
2nd November 2004, 13:37
Hi Frans,

Thanks for your competent suggestions. Now everything seems to work just as I wanted.

XML isn't that difficult ...as soon as the basic principles and terminology is understood. As usual it would have been helpfull with documentation from Baan (...SSA).
Luckilly I (/we) have Baanboard !!!

Best regards