Newbie XML Question
Mark Brownell
gizmotron at earthlink.net
Mon Dec 13 20:05:07 EST 2004
On Monday, December 13, 2004, at 12:29 PM, Bill Marriott wrote:
>
>
> <Register Station="A">
> <Purchase Date="12/13/2004" Time="14:26:03"
> DateTime="20041213142603" Order="1">
> <Buyer CustomerID="1234" />
> <Item UPC="04905004" Price="0.40"/>
> <Description>Cherry Coca-Cola</Description>
> </Purchase>
> <Purchase Date="12/13/2004" Time="14:26:14"
> DateTime="20041213142614" Order="1">
> <Buyer CustomerID="1234" />
> <Item UPC="03424005" Price="0.65"/>
> <Description>Hershey's Chocolate Bar</Description>
> </Purchase>
> <Purchase Date="12/13/2004" Time="15:09:25"
> DateTime="20041213150925" Order="2">
> <Buyer CustomerID="4567" />
> <Item UPC="02880125" Price="6.95"/>
> <Description>Marlboro Cigarettes</Description>
> </Purchase>
> </Register>
>
> In other words, Bob had two customers. The first customer bought two
> items (Order 1), and the second customer bought one item (Order 2).
>
> Each register spits out a tape like this, starting with Order=1 and
> continuing until the store closes. At the end of the day, Bob would
> like to feed these tapes into his computer running Revolution and get
> one "tape" of all his items, re-numbered sequentially.
>
> * Bob can't just tape them together (append them) because the Order
> numbers would conflict. Each register starts numbering at "1" when the
> store opens.
> * There will never be overlapping orders; only one cash register is
> active at any given time. (Bob is a sole proprietor who runs from one
> to the other.)
>
[snip]
> The problem is, I don't know how to manipulate blocks of XML like
> this. Do I have to convert the whole XML file into some kind of table
> first? Do I have to walk through each and every node and every
> attribute? Is there nothing like "sort lines of foobar ascending by
> item 5 of each?" Actually, I don't even know how to walk through the
> nodes since the functions only seem to return the first instance...
>
> I really would like to do something like select/extract all the
> Purchases where the Order ID = n and bring along all the related
> attributed and child elements. But I haven't a clue how to do that.
>
> I've gotten as far as I have through reading the "XML Demo 1" stack
> and "XML construction kit" but I've hit a wall now. Some helpful
> advice would be very welcome... and posisbly helpful for other XML
> newbies on the list.
>
> Bill
Bill,
Being new here you would not know about my pull-parsers. This task of
yours could be handled so easy with a pull parser. First of all you
could create an array of purchase objects using my pull-parser function
for creating an array out of multiple XML elements, in your case ,
purchases. So here it is done for you:
Step 1. put XML data of cash register a & cash register b into
gBothXMLtapes ( field "stashHere" )
Step 2. Use my pull-parser functions to create one array of all
purchase data (see functions below)
...paste the functions below into your application at some button
before using them.
======== Use this in a button click:
-- Paste all this below into a button & use field "stashHere"
-- to enter your XML & field "show" to see the results.
on mouseUp
put the text of field "stashHere" into gBothXMLtapes
put 1 into spot
put "" into stashAttributesDT
put "" into gTransXML
put "<Purchase " into t1
put "</Purchase>" into t2
put "" into tempXML
put getElementsArray(t1, t2, gBothXMLtapes) into bothTapesArray
repeat
put bothTapesArray[spot] into stashThis
if stashThis = empty then exit repeat
put getAttribute("DateTime", stashThis) into tAttributeDT
delete char 1 to 8 of tAttributeDT
put tAttributeDT & return after stashAttributesDT
put "<" & tAttributeDT & ">" into a1
put "</" & tAttributeDT & ">" into a2
put a1 & t1 & stashThis & t2 & a2 into zapped
put zapped & return after tempXML
add 1 to spot
end repeat
sort lines of stashAttributesDT
-- this sorting is the solution based on your XML and the use by two
cash registers.
put 1 into spot2
put "<xml>" & return into newXMLDoc
repeat for each line X in stashAttributesDT
put "<" & X & ">" into z1
put "</" & X & ">" into z2
put getElement(z1, z2, tempXML) into tXmlElement
put return & tXmlElement & return after newXMLDoc
end repeat
put "</xml>" & return after newXMLDoc
put newXMLDoc into field "show"
end mouseUp
-- That's it. You now have a newly transformed single XML document
based on the Date-Time attribute that -- will appear in the "show" text
field.
-- I hope that helps,
-- Mark
--===========================
--===========================
--Paste these functions:
-- put getElement("<record>", "</record>", tVar) into theElement
function getElement tStTag, tEdTag, stngToSch
put empty into zapped
put the number of chars in tStTag into dChars
put offset(tStTag,stngToSch) into tNum1
put offset(tEdTag,stngToSch) into tNum2
if tNum1 < 1 then
return "error"
exit getElement
end if
if tNum2 < 1 then
return "error"
exit getElement
end if
put char (tNum1 + dChars) to (tNum2 - 1) of stngToSch into zapped
return zapped
end getElement
-- put getAttribute("name", tVar) into theAttribute
function getAttribute tAttribute, strngToSearch
put empty into zapA
put quote into Qx
if char 1 of tAttribute = space then
put tAttribute & "=" & Qx into tAttributeX
else
put space & tAttribute & "=" & Qx into tAttributeX
end if
put the number of chars in tAttributeX into dChars
put offset(tAttributeX,strngToSearch) into tNum1
if tNum1 < 1 then
return "error"
exit getAttribute
end if
put tNum1 + dChars into tNumX
put offset(Qx,strngToSearch,tNumX) into tNumZ
if tNumX < 1 then
return "error"
exit getAttribute
end if
if tNumZ < 1 then
return "error"
exit getAttribute
end if
put char tNumX to (tNumX + (tNumZ - 1)) of strngToSearch into zapA
return zapA
end getAttribute
-- put getElementsArray("<record>", "</record>", tVar) into theArray
function getElementsArray tStartTag, tEndTag, StringToSearch
put empty into tArray
put 0 into tStart1
put 0 into tStart2
put 1 into tElementNum
put the number of chars in tStartTag into dChars
repeat
put offset(tStartTag,StringToSearch,tStart1) into tNum1
put (tNum1 + tStart1) into tStart1
if tNum1 < 1 then exit repeat
put offset(tEndTag,StringToSearch,tStart2) into tNum2
put (tNum2 + tStart2) into tStart2
if tNum2 < 1 then exit repeat
--if tNum2 < tNum1 then exit repeat
put char (tStart1 + dChars) to (tStart2 - 1) of StringToSearch into
zapped
put zapped into tArray[tElementNum]
add 1 to tElementNum
end repeat
return tArray
end getElementsArray
More information about the use-livecode
mailing list