Re: XML/plist parsing
Re: XML/plist parsing
- Subject: Re: XML/plist parsing
- From: Joseph Weaks <email@hidden>
- Date: Sat, 8 May 2004 02:05:27 -0500
Ok, I wrote some handlers for basic plist parsing. Only handles files
under 32k. I tested it out on several plist preference files. It
handles string, integer, real, date, boolean, data, array and dict
types (dict results are returned as a list pair). It returns lists
within lists for nested arrays and dicts. I don't thinks it's too long
to share here. I'm sure it can be improved upon in many, many ways.
-- Vanilla plist key value reader, by Joe Weaks
set keyName to "BackgroundColor"
set filePath to ((path to home folder) as string) &
"Library:Preferences:com.apple.finder.plist"
-- or
-- set filePath to (choose file) as string
set fileRef to open for access file filePath
set plistString to read fileRef
set x to getKeyValue(plistString, keyName)
close access fileRef
return x
-------------------------------------------------------
--mark Top Level Handler<B<U
on getKeyValue(plistString, theKey)
-- receives the string in plist format, and the key whose value should
be returned
set theKey to "<key>" & theKey & "</key>"
-- strips all text before the key, including the key
set theOffset to offset of theKey in plistString
set plistString to text (theOffset + (length of theKey) + 1) thru -1
of plistString
set {plistString, finalResult} to parseValue(plistString, "")
return finalResult
end getKeyValue
on parseValue(trimmedPlist, tagType)
--display dialog "Enter parseValue: " & tagType & return & "|" &
trimmedPlist
-- Sort between string, real, integer, boolean, date, data, array, or
dict
if tagType is "" then
set tagType to paragraph 1 of trimmedPlist
set the clipboard to tagType
else
set tagType to "<" & tagType & ">"
end if
if tagType contains "<string>" then
set {trimmedPlist, theResult} to parseString(trimmedPlist, "string")
set theResult to theResult as string
else if tagType contains "<real>" then
set {trimmedPlist, theResult} to parseString(trimmedPlist, "real")
set theResult to theResult as real
else if tagType contains "<integer>" then
set {trimmedPlist, theResult} to parseString(trimmedPlist, "integer")
set theResult to theResult as integer
else if tagType contains "<date>" then
set {trimmedPlist, theResult} to parseString(trimmedPlist, "date")
set theResult to theResult as string -- something else?
else if tagType contains "<data>" then
set {trimmedPlist, theResult} to parseString(trimmedPlist, "data")
set theResult to theResult as string -- something else?
else if tagType contains "<true/>" then
set {trimmedPlist, theResult} to parseString(trimmedPlist, "boolean")
else if tagType contains "<false/>" then
set {trimmedPlist, theResult} to parseString(trimmedPlist, "boolean")
else if tagType contains "<array>" then
set {trimmedPlist, theResult} to parseArray(trimmedPlist, "array")
else if tagType contains "<dict>" then
set {trimmedPlist, theResult} to parseDict(trimmedPlist, "dict")
else
display dialog "That key was not found "
end if
--display dialog "Exit parseValue: " & theResult & return & "|" &
trimmedPlist
return {trimmedPlist, theResult}
end parseValue
--mark Data Handlers<B<U
to parseString(theString, theTag)
--display dialog "Enter string: " & return & theTag & return &
theString
if theTag is "boolean" then
if paragraph 1 of theString contains "<true/>" then
set theResult to true
else
set theResult to false
end if
set theString to removeFirstParagraph(theString)
else
set beginOffset to offset of ("<" & theTag & ">") in theString
set endOffset to offset of ("</" & theTag & ">") in theString
set theResult to text (beginOffset + ((length of theTag) + 2)) thru
(endOffset - 1) of theString
-- trim the stringString
set theString to text (endOffset + ((length of theTag) + 4)) thru -1
of theString
end if
--display dialog "Exit string: " & return & theResult & return & "|" &
theString
return {theString, theResult}
end parseString
to parseArray(arrayString)
set arrayString to removeFirstParagraph(arrayString)
set arrayResult to {}
repeat
set thisParagraph to paragraph 1 of arrayString
if thisParagraph contains "</array>" then
set arrayString to removeFirstParagraph(arrayString)
exit repeat
else if thisParagraph contains "<array>" then
set {arrayString, thisResult} to parseArray(arrayString)
copy thisResult to end of arrayResult
else
set {arrayString, thisResult} to parseValue(arrayString, "")
set arrayResult to arrayResult & thisResult
end if
end repeat
--display dialog "Exit array: " & return & arrayResult & return &
arrayString
return {arrayString, arrayResult}
end parseArray
to parseDict(dictString)
set dictString to removeFirstParagraph(dictString)
set dictResult to {}
repeat
set thisParagraph to paragraph 1 of dictString
if thisParagraph contains "</dict>" then
set dictString to removeFirstParagraph(dictString)
exit repeat
else if thisParagraph contains "<dict>" then
set {dictString, thisResult} to parseDict(dictString)
copy thisResult to end of dictResult
else
set thisKey to getKeyName(thisParagraph) as list
set dictString to removeFirstParagraph(dictString)
set {dictString, thisResult} to parseValue(dictString, "")
copy thisResult to end of (thisKey)
copy thisKey to end of dictResult
end if
end repeat
--display dialog "Exit dict: " & return & dictResult & return &
dictString
return {dictString, dictResult}
end parseDict
-----------------------------------------
--mark -
--mark Utility handlers<B
to getKeyName(theString)
set beginOffset to (offset of "<key>" in theString) + 5
set endOffset to (offset of "</key>" in theString) - 1
if beginOffset > endOffset then
-- key has no value
set theResult to ""
else
set theResult to text beginOffset through endOffset of theString
end if
return theResult
end getKeyName
to removeFirstParagraph(theString)
if (count of paragraphs in theString) = 1 then
set theString to ""
else
set par1Length to length of paragraph 1 of theString
-- remove first line, including return or line feed
set theString to text (par1Length + 2) thru -1 of theString
end if
return theString
end removeFirstParagraph
-- P.S. I saw one <array/> in a plist file. Didn't know what it was
for, so didn't account for it.
_______________________________________________
applescript-users mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/applescript-users
Do not post admin requests to the list. They will be ignored.