[REBOL] parse-xml cannot be reversed Re:
From: joel:neely:fedex at: 31-Jul-2000 15:49
[bhandley--zip--com--au] wrote:
> I attempted to write a function that would take the structure that parse-xml
> generates and export it back into a valid xml file.
> But, I found that it cannot be reliably done.
>
Beg pardon, but it can be done.
> Here's an example.
> >> parse-xml {<a>teststring<b/><c/></a>}
> == [document none [["a" none ["teststring" ["b" none none] ["c" none
> none]]]]]
>
> Just looking at the structure would lead you (or your program) to conclude
> that "b" was an attribute of an element "teststring", until you realise that
> attribute lists should not have an odd number of elements.
>
No. Looking at that structure tells me that <a> has no attributes, but
has three pieces of content: a string, a <b> element, and a <c> element.
teststring
is a string and not the name of an element. We know this
because an XML element is always represented by a block with three parts:
1) name: a string
2) attributes: either none or a block of name/value pairs
3) contents: either none or a block of content items,
*each of which must be either a string or an element block*
Since "teststring" occurrs AS A TOP-LEVEL MEMBER of the content of <a>,
it must be a string.
If "teststring" were the name of an element nested inside <a>, it would
have to be the first element of its own block, something like:
[document none [["a" none [["teststring" #1 #2] ["b" none none] #3]]]]
where #1 is the attribute list of <teststring> (or none)
#2 is the content of <teststring> (or none)
#3 is the rest of the content of <a>, after <teststring> and <b>
The code below should do what you want (except for the placement of
ignorable-whitespace values, but that is left as an exercise for the
reader ;-)
-jn-
_xdump: func [
b [block!] {xml structure}
p [string!]
/local
tag
pp
was-string
][
tag: trim to-string first b
prin join copy p [join copy "<" tag]
if found? second b [
foreach [n v] second b [
prin join copy " " [trim n "=" mold v]
]
]
either none? third b [
print join copy "><" [tag "/>"]
][
print ">"
pp: join copy p " "
was-string: false
foreach x third b [
was-string: not any-block? x
either was-string [
if 0 < length? trim x [
prin join copy pp x
]
][
_xdump x pp
]
]
if was-string [print ""]
print [join copy p [copy "</" trim tag ">"]]
]
]
xdump: func [
b [block!] {the xml structure from parse-xml}
][
_xdump first third b copy ""
print ""
]