AMT Help Files
homeLION Language ReferenceSyntaxXML FunctionsXML examples

XML examples

On this page a report will be shown where an XML file is created with values from a database and then a report where that XML is consumed into a database. The purpose of these reports is to give you an idea of most XML functions that are available in AMT.

For examples of XML with namespaces please see: Producing XML with Namespaces & Consuming XML with Namespaces.

begin_definitions
const

var

    xml_document  : xml
    xml_root      : xmlnode
    xml_node1     : xmlnode
    xml_node2     : xmlnode
    xml_node3     : xmlnode

    path          : string
    xml_as_string : string

    tq_cust       : tablequery (t_customers)

booleans

end_definitions

routine main
begin_routine

    // First the declaration is set and the root node is added.
    xml_document.setxmldeclaration ('1.0','utf-8')
    xml_root := xml_document.add ('Customers')


    // A table query loop is used to add each customer's values to the xml nodes and child nodes.
    tq_cust.index (idx_customers)
    loop tq_cust
        // Per Customer a node is added to the root.
        xml_node1       := xml_root.add ('Customer')
        // This Customer node then has 5 child nodes added to it.
        xml_node2       := xml_node1.add ('CustomerNumber')
        xml_node2.value := tq_cust.custno
        xml_node2       := xml_node1.add ('Name')
        xml_node2.value := tq_cust.custname
        xml_node2       := xml_node1.add ('Address')
        xml_node2.value := tq_cust.custaddress
        xml_node2       := xml_node1.add ('City')
        xml_node2.value := tq_cust.custcity
        xml_node2       := xml_node1.add ('Accounts')

        // The 'Accounts' node has its own child nodes
        // with an attribute to show what type of account it is.
        if tq_cust.depaccnr <> ''
            xml_node3       := xml_node2.add ('Account')
            xml_node3.value := tq_cust.depaccnr
            xml_node3.attribute.add ('Type','Deposit')
        endif
        if tq_cust.savsaccnr <> ''
            xml_node3       := xml_node2.add ('Account')
            xml_node3.value := tq_cust.savsaccnr
            xml_node3.attribute.add ('Type','Savings')
        endif

    endloop


    // After adding all the customer (child) nodes
    // and filling them with values from the database,
    // the xml document is written to an xml file with the save function.
    path := 'BankCustomers.xml'
    xml_document.save(path)

    // If there was a problem with saving the xml document,
    // the system item getlastresult will have complementary information
    sme (getlastresult)

    // Besides saving the xml document to an xml file,
    // it is also possible to assign the xml document to a string.
    xml_as_string := xml_document.gettext ()

    // After exporting the xml document to both a file and to a string,
    // the xml document is cleared from memory so that a new xml document can be created using the same variables.
    xml_document.clear ()

end_routine

When used on a database filled with randomly generated values, this results in an XML file with the following structure:

<?xml version="1.0" encoding="utf-8"?>
<Customers>
  <Customer>
    <CustomerNumber>123546</CustomerNumber>
    <Name>Nora Lucas</Name>
    <Address>811 Ridge Street</Address>
    <City>Austin</City>
    <Accounts>
      <Account Type="Deposit">NL74ABNA0574516842</Account>
      <Account Type="Savings">NL12DLBK0283806315</Account>
    </Accounts>
  </Customer>
  <Customer>
    .....
  </Customer>
</Customers>

An XML with 8 customers for use with the next report can be downloaded here: BankCustomers.xml

begin_definitions
const

var

    xml_document  : xml
    xml_root      : xmlnode
    xml_node1     : xmlnode
    xml_node2     : xmlnode
    xml_node3     : xmlnode
    xml_nodes     : xmlnodes

    xml_fc        : filecontrol
    xml_as_string : string
    result_ok     : boolean
    path          : string
    hasnextsib    : boolean value true
    hasnextsib2   : boolean value true
    tq_cust       : tablequery (t_customers)

booleans

end_definitions

routine main
begin_routine

    path          := 'BankCustomers.xml'


    // As alternative method to the load function, the xml file content is read into a string
    // Some characters with diacritics are then replaced by characters without diacritics.
    // Then the string is parsed as xml document and checked if it is valid.
    xml_as_string := xml_fc.givefilecontent (path, -1)
    inspect (xml_as_string)
        replacing (all, ['é','ä','ç'], ['e','a','c'])
    endinspect
    xml_document.parse (xml_as_string) RESULTOKTO result_ok
    if not result_ok
        sme ('Invalid XML file: ', path)
        exit
    endif


    // For completeness the Load function code is also given in a block comment:

        { // Load the XML and check if it is valid.
        xml_document.load (path)
        if xml_document.filename = ''
        sme ('Invalid XML file :', path)
        exit
        endif }

    // Set the root node and the first customer in xml_node1
    xml_root  := xml_document.root
    xml_node1 := xml_root.firstchild
    if resok = False
        sme ('Empty XML file :', path)
        exit
    endif


    // Loop through all the customer nodes
    // do this until there is no next sibling
    loop while hasnextsib

        // Set the first customer child node in xml_node2
        xml_node2 := xml_node1.firstchild

        // Loop through all the customer child nodes and
        // move the values to the corresponding tablequery fields
        // do this until there is no next sibling
        loop while hasnextsib2
            startcase xml_node2.name
            case 'CustomerNumber'
                tq_cust.custno := xml_node2.value
            case 'Name'
                tq_cust.custname := xml_node2.value
            case 'Address'
                tq_cust.custaddress := xml_node2.value
            case 'City'
                tq_cust.custcity := xml_node2.value
            case 'Accounts'
                // Check if there are account child nodes
                if xml_node2.haschildnodes
                    // Set all child nodes of the node Accounts in xml_nodes
                    // This could also be achieved by using the 'Selectnodes' function
                    xml_nodes := xml_node2.getelementsbytagname ('Account')
                    // Loop through the Account nodes in xml_nodes
                    loop for each xml_node3 in xml_nodes
                        // If there is exactly one attribute per Account node,
                        // use it to fill the correct table query field
                        if xml_node3.attribute.count = 1
                            if xml_node3.attribute[1].value = 'Deposit'
                                tq_cust.depaccnr := xml_node3.value
                            elseif xml_node3.attribute[1].value = 'Savings'
                                tq_cust.savsaccnr := xml_node3.value
                            endif
                        endif
                    endloop
                endif
            endcase
            // Set the next customer node in xml_node2
            // when there is no next node, Set the loop flag to false
            xml_node2   := xml_node2.nextsibling
            hasnextsib2 := resok
        endloop

        // After having moved all the values of a customer to the table query
        // insert the values into the database if the mandatory customer number field is not zero
        // then clear the table query
        if tq_cust.custno <> 0 then tq_cust.insert ()
        tq_cust.clear ()

        // Reset the loop flag for the next customer
        hasnextsib2 := true

        // Set the next customer in xml_node1
        // when there is no next node Set the loop flag to false
        xml_node1   := xml_node1.nextsibling
        hasnextsib  := resok

    endloop

    sme (path, 'was loaded into the Customer Database')

end_routine

Contents

 Go to top