Documention for: rebelxml.r Created by: reboltof on: 25-Apr-2006 Last updated by: reboltof on: 28-Apr-2006 Format: text/editable Downloaded on: 18-Apr-2024 RebelXML - User Manual Version: 1.2 Date: 28-apr-06 Author: Christophe Coussement (COU) Contact: reboltof-at-yahoo-dot-com

History:

\table Date Version Description Author =row 28-avr-05 1.2 Correct typo (thanks to 10djé !) COU =row 27-avr-05 1.1 Add Unit tests examples COU =row 25-avr-05 1.0 Initial COU /table
\note Warning RebelXML is currently a BETA version, released in the purpose of getting feedbacks and bugs reports from the users. Avoid to use this script into a production environnement, as certain key-functionnalities could be changed. This documentation has no pretention of being complete, and will be reworked as the feedbacks come and the project is being developped. /note === What is RebelXML ? RebXML is a SAX-like XML access-functions library, which allows the user to read/write/create/delete XML data in a very easy way. RebXML works directly with the XML data, without the need of any to REBOL block convertion, because it uses the great power of the REBOL parser. === What do I need to run RebelXML ? 1. Download the script %RebelXML.r from http://www.rebol.org 2. Be sure you're running REBOL/View >= 1.3 and launch the console 3. Run the script into the console: do %RebelXML.r or include it into a script 4. Use the functions described into this document === Extracting data from XML data --- The function 'load-xml-data USAGE: LOAD-XML-DATA data DESCRIPTION: load xml data into xml-data word LOAD-XML-DATA is a function value ARGUMENTS: data -- XML data to load (Type: string) --- The function 'get-xml-data USAGE: GET-XML-DATA path /content /attribute att-name /with-attribute w-att-name w-att-data DESCRIPTION: extract requested data from xml GET-XML-DATA is a function value. ARGUMENTS: path -- the path pointing to the data (Type: path word) REFINEMENTS: /content -- if content value is requested /attribute -- if attribute value is requested \in att-name -- name of the attribute (Type: word) /in /with-attribute -- qualify a content \in w-att-name -- name of the attribute (Type: word) w-att-data -- value of the attribute (Type: string) /in --- Usage example 1: using tags Let start with this simple example... Consider this simple XML code example (from http://www.w3schools.com/xml/xml_examples.asp), placed into the file %note.xml: Tove Jani Reminder Don't forget me this weekend! And we want to extract the 'to' and 'from' information... Proceed as following: 1. Run the script into the console: >> do %RebelXML.r 2. Load the XML code into RebelXML: \note The XML code must be loaded as a string! /note >> load-xml-data read %note.xml == { Tove Jani Reminder Don't forget me this weekend! > get-xml-data/content 'note/to == ["Tove"] >> get-xml-data/content 'note/from == ["Jani"] Using the /content refinement, you specify to RebelXMl that you are interested into the content of the tag, not anything else. Simple, isn't it ? --- Usage exemple 2: using attributes Let's consider the file %note.xml, containing multiple notes, each one identified by an unique identifier 'id': Tove Jani Reminder Don't forget me this weekend! Jani Tove Re: Reminder I will not! We are only interested in the values contained into the note 'p502'. To extract those specific information, we've to specify the required attribute: >> load-xml-data read %note.xml == { Tove Jani Reminder ... >> get-xml-data/content/with-attribute 'messages/note 'id "p502" == [{ Jani Tove Re: Reminder I will not! ... If we are searching for more specific information, let's say the field 'to', we've to proceed in 2 requests: >> load-xml-data read %note.xml == { Tove Jani Reminder ... >> load-xml-data first get-xml-data/content/with-attribute 'messages/note 'id "p502" == { Jani Tove Re: Reminder I will not! ... >> get-xml-data/content 'to == ["Jani"] Perhaps do we want to know which id's are available into our XML data ? Let do this: >> load-xml-data read %note.xml == { Tove Jani Reminder ... >> get-xml-data/attribute 'note 'id == ["p501" "p502"] === Creating a XML data from scratch The base idea is quite simple: if you try to write something at the end of a path wich does not exists yet, RebelXML will construct it for you ! You can use those functions to proceed: --- The function 'set-xml-data USAGE: SET-XML-DATA path /content data /attribute att-name att-value /with-attribute w-att-name w-att-data DESCRIPTION: set path, content and/or attribute into xml-data SET-XML-DATA is a function value. ARGUMENTS: path -- access path (Type: word path) REFINEMENTS: /content -- set a content \in data -- content data (Type: string) /in /attribute -- set an attribute \in att-name -- attribute name (Type: word) att-value -- attribute data (Type: string) /in /with-attribute -- specify a tag with a given attribute \in w-att-name -- name of the attribute (Type: word) w-att-data -- value of the attribute (Type: string) /in --- The function 'clear-xml-data USAGE: CLEAR-XML-DATA DESCRIPTION: clears existing data into internal cache CLEAR-XML-DATA is a function value. --- The function 'show-xml-data USAGE: SHOW-XML-DATA DESCRIPTION: returns data from internal cache SHOW-XML-DATA is a function value --- The function 'set-xml-quote USAGE: SET-XML-QUOTE user-quote DESCRIPTION: set user quote preference (default is 'simple) SET-XML-QUOTE is a function value. ARGUMENTS: user-quote -- May be 'simple or 'double (Type: word) --- Usage example As illustration, let's try to reconstitue the "note" we used in the preceding part of this documentation: To begin from a healthy base, let's clear the buffer: >> clear-xml-data == "" And add the tags and data we need: >> set-xml-data/content 'note/body "Don't forget me this weekend!" == {Don't forget me this weekend!} >> set-xml-data/content 'note/heading "Reminder" == {ReminderDon't forget me this weekend!} >> set-xml-data/content 'note/from "Jani" == {JaniReminderDon't forget me this weekend!} >> set-xml-data/content 'note/to "Tove" == {ToveJaniReminder Don't forget me this weekend!} and we can get the generated content by using 'show-xml-data: >> show-xml-data == {ToveJaniReminder Don't forget me this weekend!} or, if indented: { Tove Jani Reminder Don't forget me this weekend! } \note Caution Because RebelXML is inserting the new tags into the existing data, we need to insert first the last data of the set, if the tag order matters. A way to easily handle this is shown next to this. /note We could also use a more "REBOLish" code and write: >> data: [ [ 'note/to "Tove" [ 'note/from "Jani" [ 'note/heading "Reminder" [ 'note/body "Don't forget me this weekend!" [ ] == [ 'note/to "Tove" 'note/from "Jani" 'note/heading "Reminder" 'note/body "Don't forget me this weekend!" ] >> reverse data == ["Don't forget me this weekend!" 'note/body "Reminder" 'note/heading "Jani" 'note/from "Tove" 'note/to ] >> foreach [content tag] data [set-xml-data/content tag content] == {ToveJaniReminder Don't forget me this weekend!} === Modifiying existing XML data The same 'set-xml-data function can be used for modifying existing contents. --- Usage example Let's start from our note: >> load-xml-data read %note.xml == { Tove Jani Reminder Don't forget me this weekend! > set-xml-data/content 'note/to "Frebus" == { Frebus Jani Reminder > probe show-xml-data { Frebus Jani Reminder Don't forget me this weekend! } === Supplementary note: Unit test used for script validation For those who are curious to know what "Test Driven Development" is, here is an example of some tests I used for the validation of the function 'set-xml-data. \note Note You will need the %RUn.r script for trying those unit tests. You can find it at: http://www.rebol.org/cgi-bin/cgiwrap/rebol/view-script.r?script=run.r /note ;======================== ;=== UNIT TEST === ;======================== ;=== TASK X2.1 - set-data === ;=========================================================================== ;--- set test context setup: does [ #include %RebelXML.r ] ;=========================================================================== ;--- create new path test-set-data-1a: does [ assert set-xml-data/content 'result/section/section "test" ] ;--- test-set-data-1b: does [ assert-equal show-xml-data {
test
} ] ;--- complete partial path w test-set-data-2a: does [ load-xml-data {
} assert set-xml-data/content 'result/section/item/time "20" ] test-set-data-2b: does [ assert-equal show-xml-data {
} ] ;--- test-set-data-3a: does [ assert set-xml-data/content 'result/section/section/date "26-jan-06" ] test-set-data-3b: does [ assert-equal show-xml-data {
26-jan-06
} ] test-set-data-4a: does [ load-xml-data {
} assert set-xml-data/attribute 'result/section 'ident "20103" ] test-set-data-4b: does [ assert-equal show-xml-data {
} ] test-set-data-4c: does [ assert set-xml-data/attribute 'result/section 'type "file" ] test-set-data-4d: does [ assert-equal show-xml-data {
} ] test-set-data-4e: does [ load-xml-data {
} set-xml-quote 'double assert set-xml-data/attribute 'result/section 'ident "20103" ] test-set-data-4f: does [ assert-equal show-xml-data {
} ] test-set-data-5a: does [ load-xml-data {
} set-xml-quote 'simple assert set-xml-data/content/with-attribute 'result/section "test" 'ident "20104" ] test-set-data-5b: does [ assert-equal show-xml-data {
test
} ] test-set-data-6a: does [ load-xml-data {test content
section content
} assert set-xml-data/content 'result/section "new content" ] test-set-data-6b: does [ assert-equal show-xml-data {test content
new content
} ] ;=========================================================================== ;--- clean up test context teardown: does [] ;===========================================================================