0

This question ia about writing XML data from a LiveCode stack to a file. Chapter 6.7 of the User's guide talks about the XML functions LiveCode provides. I am looking for examples which show how to construct an XML file and write it to a disk file.

http://support.runrev.com/tutorials/xmldemo.rev.gz is a tutorial stack about how to use the revNNN XML functions of LiveCode.

It has an example

  ....
  local tDocID, tParentNode, tSubNode

  -- get the document ID for the current XML tree
  put fld "DocID" into tDocID

  -- specify the root node for the XML tree
  put "/employeeTable" into tParentNode

  revAddXMLNode tDocID, tParentNode, "employee", ""
  put the result into tSubNode

  -- add the IDnum attribute to the newly created data record
  revSetXMLAttribute tDocID, tSubNode, "IDnum", "1"

  -- add the remaining data elements, checking for error after each addition
  revAddXMLNode tDocID, tSubNode, "firstName", "Steve"
  revAddXMLNode tDocID, tSubNode, "lastName", "Jobs"
  revAddXMLNode tDocID, tSubNode, "roomNum", "001"
  revAddXMLNode tDocID, tSubNode, "phoneExt", "345"
  revAddXMLNode tDocID, tSubNode, "parkingSlot", 100

The result

  <?xml version="1.0"?>
  <employeeTable>

    <employee IDnum="1">
    <firstName>Steve</firstName>
    <lastName>Jobs</lastName>
    <roomNum>001</roomNum>
    <phoneExt>345</phoneExt>
    <parkingSlot>100</parkingSlot>
    </employee>

 </employeeTable>

Are there libraries which make writing XML texts easier by providing convenience functions so that I do not need to keep track of nodes when adding nested structures?

Something like

startXML "theEmployees.xml"  -- gives the file name 
startTag "employeetable"
  startTag "employee"
    addAttribute "IDnum", 1
    startTag "firstName"
      writeContent "Steve"
    closeTag
    -- or
    writeNode "lastname", "Jobs"
    writeNode "roomnum", "001"
    -- ....
   closeTag -- employee
closeTag -- employeeTable
closeXML

It is relatively easy to write a couple of functions like this but the question is. Are there established ways of writing out XML text to a file in LiveCode?

tshepang
  • 12,111
  • 21
  • 91
  • 136
z--
  • 2,186
  • 17
  • 33
  • This is the version control library by Mark Wieder (public domain) contains some XML writing procedures. http://revonline2.runrev.com/stack/686/libVersionControl – z-- May 06 '13 at 09:53
  • There is a chapter about creating and reading XML files in my book "Programming LiveCode for the Real Beginner". – Mark Jun 15 '13 at 11:19

4 Answers4

1

If you just want to write XML (and not create revXMLTrees) you can write your own functions. How about this for a starter:

local _tags
local _xml
local _level
local _tabs

function q pText
   return quote & pText & quote
end q

on startXML
   put "<?xml version=" & q("1.0") & "?>" & return into _xml
   put 0 into _level
   put empty into _tabs
   put empty into _tags
end startXML

on startTag pTag
   put _tabs & "<" & pTag & ">" & return after _xml
   add 1 to _level
   put pTag into _tags[_level]
   put tab after _tabs  
end startTag

on closeTag
   delete char 1 of _tabs
   put _tabs & "</" & _tags[_level] & ">" & return after _xml
   # Do a 'delete variable _tags[_level]' if you really want to clean the array as you go 
   subtract 1 from _level
end closeTag

on addAttribute pAttribute, pValue
   # This should go into the last tag, but as we have "proper XML" so far we can backtrace two chars (">" and newline)
   put space & pAttribute & "=" & q(pValue) before char -2 of _xml
end addAttribute

on writeContent pContent
   put _tabs & pContent & return after _xml
end writeContent

on writeNode pNode, pValue
   put _tabs & "<" & pNode & ">" & pValue & "</" & pNode & ">" & return after _xml
end writeNode

getProp xml
   return _xml
end xml

Put that script on the card or stack then you can do:

startXML
startTag "employeetable"
startTag "employee"
addAttribute "IDNum", 1
startTag "firstName"
writeContent "Steve"
closeTag
writeNode "lastName", "Jobs"
writeNode "roomnum", "001"
writeNode "phoneExt", "345"
writeNode "parkingSlot", "100"
closeTag
closeTag
put the xml of this card into field 1

This is of course not a complete solution as it will not do any validation of your input, and the format might not be exactly what you want, but I guess it can get you started.

hliljegren
  • 426
  • 3
  • 9
  • Yes, this is what I am aiming at. Thank you. I'll continue with this implementation and will do some tests. Then I'll post the result. – z-- May 08 '13 at 14:39
0

The version control library by Mark Wieder (public domain) contains some XML writing procedures which might be considered.

http://revonline2.runrev.com/stack/686/libVersionControl

--> xml

/** ------------------------------
* XML.StartTag
*
* Return <tag>
* Convert embedded commas and spaces as part of the process.
* ------------------------------
*/
private function XML.StartTag pTag
    if comma is in pTag then
        replace comma with kMagicComma in pTag
    end if
    if "&" is in pTag then
        replace "&" with kAmpersand in pTag
    end if
    if space is in pTag and "=" is not in pTag then
        replace space with kMagicSpace in pTag
    end if
    return "<" & pTag & ">"
end XML.StartTag

/** ------------------------------
* XML.EndTag
*
* Return </tag>
* Convert embedded commas and spaces as part of the process.
*
* @pTag : the tag of interest
* ------------------------------
*/
private function XML.EndTag pTag
   if comma is in pTag then
      replace comma with kMagicComma in pTag
   end if
   if space is in pTag and "=" is not in pTag then
      replace space with kMagicSpace in pTag
   end if
   return "</" & pTag & ">" & cr
end XML.EndTag

/** ------------------------------
* XML.Element
*
* return <tag>value</tab>
* base64encode the value item if necessary
* ------------------------------
*/
private function XML.Element pTag, pValue
    local tIsBinary
    local tTest

    put false into tIsBinary
    if pTag is in "htmlText, script, imagedata" then
        put true into tIsBinary
    else
        repeat for each byte tByte in pValue
            put chartonum(tByte) into tTest
            -- see if the char is printable
            if tTest < 32 or tTest > 128 then
                put true into tIsBinary
                -- no need to look further
                exit repeat
            end if
        end repeat
    end if
    -- can't have binary data in xml
    if tIsBinary then
        put "base64decode(" && q(base64encode(pValue)) && ")" into pValue
    end if
    return XML.StartTag(pTag) & pValue & XML.EndTag(pTag)
end XML.Element

--> Utilities

function q pText
    return quote & pText & quote
end q
z--
  • 2,186
  • 17
  • 33
  • 1
    I should add that while I find it easier to use functions like this to generate xml files than to use the built-in funcitons, the built-in routines are very handy for reading and parsing xml files. – mwieder May 06 '13 at 18:10
  • Yes, I am looking for a LiveCode **XML Writing** functions. – z-- May 07 '13 at 09:57
0

The LiveCode documentation (dictionary) contains many XML-related functions. These functions are sufficient to navigate and manipulate any XML tree. However, the XML external doesn´t handle indices very well, which means you need to keep track of those yourself. E.g. you can loop through an XML tree using their index number, check the ID number of each tree node and use the node with the correct ID number. Let me know if you need an example.

For everything else, figuring out how a library works is just as complicated as figuring out the XML functions themselves. Just read the built-in docs.

Mark
  • 2,380
  • 11
  • 29
  • 49
  • I gave an example how such an XML writing API looks like in the question. I am asking for simple ways of constructing an XML file. See my other answer. An example for Java is here http://java.ociweb.com/mark/programming/wax.html . Building a DOM structure to describe a large XML document won't work because it won't fit in memory. Even if it did, it's not a simple API to use. – z-- May 07 '13 at 09:33
0

It seams it'll not work with UTF8 text (accented characters like ąęćś) as node values.