Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Simple XML

 [1/8] from: tbrownell::veleng::com at: 7-Mar-2004 0:04


XML can be both simple and complex. This site is devoted to the creation of the necessary tools and docs to make the complex simple too using Rebol. http://compkarori.com/vanilla/display/Simple+XML

 [2/8] from: tbrownell:veleng at: 9-Mar-2004 13:19


Is there any available scripts that turn xml into rebol blocks? So that ... <root> <person> <name> <fname> Bob </fname <lname> Smith </lname> </name> </person> </root> becomes.. root [ person [name [fname "Bob" lname "Smith"]]] TB

 [3/8] from: doug:vos:eds at: 9-Mar-2004 16:37


I think this does what you want. Purpose: "Library analogous to perl XML::Simple." Only works with simple XML. Does not handle namespaces="values" inside tags. REBOL [ Title: {xml-test13.r} File: %xml-test13.r Date: 21-Oct-2003 Requires: {rebol version 2.5.6 or higher} ] do %/d/xml/xml-simple-v0.1.2.r bklist: XMLin %/d/xml/booklist3.xml probe bklist XMLout %/d/xml/booklist4.xml bklist ;===================================== REBOL [ Title: "XML-Simple (Library)" Date: 20-Oct-2003 Version: 0.1.2 File: %xml-simple.r Author: "Doug Vos" Email: [doug--vvn--net] Purpose: "Library analogous to perl XML::Simple." History: [ 0.1.0 [18-Oct-2003 {Began script.} "DJV"] 0.1.2 [20-Oct-2003 {Added XMLin function, added XMLout.} "DJV"] ] ] ;-------------------------------------------------------------------- end-tag?: func [ {Test for an ending xml or html style tag. eg. </thing>} item [any-type!] {The item to examine} ][ either (tag? item) [ either (find item "/") [true][false] ][ false ] ] ;-------------------------------------------------------------------- begin-tag?: func [ {Test for a begining xml or html style tag. eg. </thing>} item [any-type!] {The item to examine} ][ either (tag? item) [ either (find item "/") [false][true] ][ false ] ] ;-------------------------------------------------------------------- tag-to-string: func [ {Convert a simple html or xml tag to a string.} xtag [tag!] {The tag to convert.} ][ trim/all replace/all to-string xtag "/" "" ] ;------------------------------------------------------------------- simple-tag?: func [ {Test for tag with simple structure like <tag>a few words</tag>} item [any-type!] {The item to examine.} xml [block!] {The whole block we are examining.} /local atag ztag xs ][ either (tag? item) [ atag: to-tag (tag-to-string item) ztag: to-tag rejoin ["/" (tag-to-string item)] xs: find xml atag either ( all [ (tag? pick xs 1) (string? pick xs 2) (ztag = (pick xs 3))] ) [true][false] ][ false ] ] ;------------------------------------------------------------------- multi-tags?: func [ {Test for multiple occurences of tag like <book>...</book> as found in something like <booklist><book>...</book><book>...</book></booklist>} item [any-type!] {The item to examine.} xml [block!] {The whole block we are examining.} /local atag ztag xs ][ either (tag? item) [ atag: to-tag (tag-to-string item) ztag: to-tag rejoin ["/" (tag-to-string item)] xs: find xml ztag either ( all [ (tag? pick xs 1) (atag = (pick xs 2))] ) [true][false] ][ false ] ] ;-------------------------------------------------------------------- XMLin: func [ {Provide a XMLin function analogous to perl XML::Simple XMLin().} xmli [url! file! string!] {The xml url, file or xml-text.} /local xstr xml item ][ xstr: make string! 1000 xml: load/markup xmli ; remove the strings that are only 'newline and empty space remove-each x xml [empty? trim x] ; Ignore the first tag, ; which is always something like <?xml version="1.0"?> xml: copy at xml 2 append xstr "[" foreach item xml [ append xstr " " if (begin-tag? item) [ if (multi-tags? item xml) [append xstr " [ "] append xstr tag-to-string item if (not simple-tag? item xml) [append xstr " [ "] ] if (string? item) [ append xstr mold item ] if (end-tag? item) [ if (not simple-tag? item xml) [append xstr " ]"] if (multi-tags? item xml) [append xstr " ] "] ] ] append xstr "]" load xstr ] ;-------------------------------------------------------------------- XMLout: func [ {Provide a XMLout function analogous to perl XML::Simple XMLout().} xmlf [file!] {The xml file to create.} xblock [block!] {The data to populate xml file.} /local xstr item ][ xstr: make string! 1000 append xstr {<?xml version="1.0"?>^/} XMLout.block xstr xblock print xstr write xmlf xstr ] ;-------------------------------------------------------------- XMLout.block: func [ {Process the block according to rules.} xml.tree [string!] {The xml-tree we are creating.} item [block!] {The pre xml-block.} ][ either (multi-block? item) [ foreach x item [ XMLOut.block xml.tree x ] ][ either (multi-word-pair? item) [ foreach [w v] item [ XMLOut.block xml.tree (reduce [w v]) ] ][ if (simple-word-value-pair? item) [ append xml.tree rejoin ["<" item/1 ">" item/2 "</" item/1 ">" newline] ] if (complex-block-pair? item) [ append xml.tree rejoin [ "<" item/1 ">"] XMLOut.block xml.tree item/2 append xml.tree rejoin [ "</" item/1 ">" newline] ] ] ] ] ;-------------------------------------------------------------------- multi-word-pair?: func [ {Examine block to see if it contains a block with multiple word pairs. Return TRUE if item is pattern [word "value" word "value"] or TRUE if item is pattern [word "value" word [block]] } item [any-type!] {Item to examine.} ][ either block? item [ either ((length? item) >= 4) [ all [(word? item/1) (word? item/3)] ][ false ] ][ false ] ] ;-------------------------------------------------------------------- multi-block?: func [ {Examine block to if it contains 2 or more blocks} item [any-type!] {Examine item and return TRUE if multi-block.} ][ either block? item [ either ((length? item) >= 2) [ all [(block? item/1) (block? item/2)] ][ false ] ][ false ] ] ;-------------------------------------------------------------------- simple-word-value-pair?: func [ {Examine block to see if simple pair like [word! single-value] } item [any-type!] {Examine item and return TRUE if simple pair.} ][ either block? item [ either ((length? item) = 2) [ all [(word? item/1) (not block? item/2)] ][ false ] ][ false ] ] ;-------------------------------------------------------------------- complex-block-pair?: func [ {Examine block to see if complex pair [word! [block]] } item [any-type!] {Examine item and return TRUE if complex pair.} ][ either block? item [ either ((length? item) = 2) [ all [(word? item/1) (block? item/2)] ][ false ] ][ false ] ] ;--------------------------------------------------------------------

 [4/8] from: maximo:meteorstudios at: 9-Mar-2004 16:46


A: {<root><person><name><fname>Bob</fname><lname>Smith</lname></name></person></root>} B: parse-xml a probe B == [document none [["root" none [["person" none [["name" none [["fname" none ["Bob"]] ["lname" none ["Smith"]]]]]]]]]] of course beware of line feeds... I wonder what those extra block nestings are for !? if you put the original code with linefeeds and pre and post spaces, you get labels before each block which equate to that spacing with the linefeeds !? I don't get how that can be of any use... can someone explain? -MAx --- You can either be part of the problem or part of the solution, but in the end, being part of the problem is much more fun.

 [5/8] from: joel:neely:fedex at: 9-Mar-2004 15:47


Hi, Terry, No script needed. PARSE-XML does what you're asking (given that you can use the block convention it creates -- see below). T. Brownell wrote:
> Is there any available scripts that turn xml into rebol blocks? So that ... > >> xml-stuff: {<root>
{ <person> { <name> { <fname> { Bob { </fname { <lname> { Smith { </lname> { </name> { </person> { </root>} == {<root> <person> <name> <fname> Bob </fname <lname> Smith </ln...
>> block-stuff: parse-xml xml-stuff
== [document none [["root" none ["^/ " ["person" none ["^/ " ["name" none ["^/ " ["fname" none ["^/ Bob^/ ... The convention is that each XML element is represented by a 3-item block, containing: 1) the name of the element/tag as a STRING! 2) attributes (as a block of name/value pairs) or NONE if no attrs 3) contents (as a block of the content items -- strings for text and blocks for child elements) or NONE if no contents *AT*ALL* IgnorableWhiteSpace is not ignored, but appears as STRING! content. The entire XML string is wrapped in a mythical element whose tag is the WORD! DOCUMENT with no attributes. If you juat want the XML content, just take FIRST THIRD of the result of PARSE-XML, as in (the line breaks were added for email formatting, and should be eliminated if you try to cut and paste):
>> x: {<top><middle place='between'>
<bottom>down</bottom></middle></top>} == {<top><middle place='between'> <bottom>down</bottom></middle></top>}
>> print mold first third parse-xml x
["top" none [["middle" ["place" "between"] [["bottom" none ["down"]]]]]]
>>
HTH! -jn- -- Single bit errors are corrected. Joel Neely Double bit errors are detected. joel dot neely Undetected errors are ignored. at fedex dot com

 [6/8] from: rebol:gavinmckenzie:fastmail:fm at: 9-Mar-2004 17:42


*de-cloak* The third item of each block holds the children of the particular element node. For the XML document itself there can only be one child node (the document element) so having a block around the document element doesn't do any good, but the extra nesting that is found after "document none" is there I expect as just a matter of consistency. i.e. for no particular good reason. Gavin. On Tue, 9 Mar 2004 16:46:45 -0500, "Maxim Olivier-Adlhoch" <[maximo--meteorstudios--com]> said:

 [7/8] from: tbrownell:veleng at: 9-Mar-2004 17:36


Thanks Doug, that's perfect. Although my XML didn't have a beginning <?xml version="1.0"?> tag so it choked at first. Could add a.. if found? find first xmli "version" [xml: copy at xml] The great thing about Dougs functions is the path structure they create allows one to march through the xml file changing things with ease. See http://compkarori.com/vanilla/display/Simple+XML for more info. Now we have a incredibly powerful, yet SIMPLE way to open a xml document... process the contents in an almost endless way, and write the xml back in Rebol. TB 2Vos, Doug wrote:

 [8/8] from: doug:vos:eds at: 10-Mar-2004 8:31


Reply to Joel - My version of Simple-XML overcomes the problem you identify...
>>(given that you can use the block convention it creates -- see below).
With the library I provided, you can us XMLin and XMLout and you can also easily handle the blocks created like root/person/name/fname -- instead of some odd block structure with no easy way to point to the items you want to handle. Again, it is not a full xml, but works for many simple XML situations like config files, etc.