Re: More XML stuff - reading - changing - and writing the file
Re: More XML stuff - reading - changing - and writing the file
- Subject: Re: More XML stuff - reading - changing - and writing the file
- From: Emmanuel LEVY <email@hidden>
- Date: Fri, 11 Jun 2010 23:07:43 +0200
I don't think you need any "try". XMLXpath just builds a list. Maybe
the list is empty. XMLRemove supports a list, including the empty list.
Emmanuel
Thanks for the great comments. Yes, they are appreciated.
I actually I ended up putting a "try" handler inside the repeat loop
since the XML is generated by an external application and may or may
not include all of the values to be removed. I'm not sure if the
xpath example you give would accomplish this using the "or"?
Steve
Steve Thompson
email@hidden
On Jun 10, 2010, at 5:28 PM, Emmanuel LEVY wrote:
Wow.
You're very welcome.
If you would like my comments on your new code, they are minor:
1. (very minor) it's enough to call xmlsave after end repeat,
2. (very minor unless you have productivity/speed issues) you could
build a more complicated xpath like in [ (@id="FIRST_STRING") or
(@id="SECOND_AND_SO_ON") or (etc.) ] instead of calling a loop,
3. (very important, can bite you) there is no safe way to insert a
string with such a thing as quoted form. Believe me, quoted form is
a little good, but not very good. The only bulletproof way is to
use a "xpath variable":
XMLXPath " blah [@id = $thestring] " xpath variables
{theString:item i of fieldsToRemove}
Emmanuel
Thanks for that great reply. Turned my jumbled mess into a lean,
mean machine. Not to mention I understand how to use XMLLib
correctly now. Thanks.
A few things for the benefit of someone that may have the same
question now or in the future and come across this:
My XML looks like this:
<?xml version="1.0"?>
<session>
<values>
<value id="PA_MD_CUST_ANGLE">
<string xml:space="preserve">ANGLE</string>
</value>
<value id="PA_MD_CUST_SCENE">
<string xml:space="preserve">SCENE</string>
</value>
<value id="CUST_SIZE">
<bigint>4036221402</bigint>
</value>
<value id="PA_MD_CUST_CLIPIT_ANNOTATION_REQUEST">
<bool>true</bool>
</value>
...and so on...
</values>
</session>
And, I wanted to remove a number of <value>...</value> defined by
value id's as: set fieldsToRemove to {"FIELD_NAME_ONE",
"FIELD_NAME_TWO",...}
I ended up with:
set XMLtext to XMLOpen tempXML
set the_root to XMLRoot XMLtext
repeat with j from 1 to count of items in fieldsToRemove
set theXMLPath to "values[1]/value[@id=" & quoted form of (item
i of fieldsToRemove) & "]"
XMLRemove (XMLXPath the_root with theXMLPath)
XMLSave XMLtext
end repeat
XMLClose the_root
I struggled a bit with getting the XMLXPath argument correct
(quotes and such) but it works as shown.
Thanks again Emmanuel and everyone.
Steve Thompson
email@hidden
On Jun 9, 2010, at 4:50 PM, Emmanuel LEVY wrote:
Sorry I'm late with my mails, but maybe you are interested in a
few minor comments.
try
close access POSIX file tempXML
end try
don't do that, xmllib will do all the file stuff for you
-- open XMLfile and prep as XML
set xmlFileText to (open for access POSIX file tempXML with
write permission)
set XMLtext to XMLOpen (read xmlFileText for (get eof
xmlFileText))
don't do that, you're assuming you know the file's encoding, it's
safer to let xmllib assume for you :
set xmltext to xmlopen tempxml
is enough. I assume tempxml is a posix path: "/User/steve/blah/
thefile.xml"
-- find the index of the XML entry of interest
set the_root to XMLRoot of XMLtext
set the_child to XMLChild the_root index 1
XMLNodeInfo the_child
set theCount to the XMLCount of the_child
repeat with i from 1 to theCount
set the_child2 to XMLChild the_child index i
set theValueID to item 2 of attribute of (XMLNodeInfo the_child2)
if theValueID is "ASSET_TYPE" then set theENTRY to i
end repeat
-- once the index is found, remove that entry
set theOne to XMLChild the_child index theENTRY
XMLRemove theOne
The idea in XML is that nodes have tag names.
Let's assume you know the tag name of the_child, say <father>.
Let's assume you know the tag name of the_child2, say <sonny>.
Let's assume you know the name of the first attribute of <sonny>,
it's "type". Then:
the "the_child2" you're wanting is:
XMLXPath the_root with " father[ 1 ] / sonny [ @type =
'ASSET_TYPE' ] "
This reads from left to right: take all the direct children of
the root whose tag name is father. Take the first of them. Take
all its "sonny" children. Select the one(s) whose attribute with
name "type" has value "ASSET_TYPE".
Thus the block above can be:
XMLRemove XMLXPath the_root with " father[ 1 ] / sonny [ @type =
'ASSET_TYPE' ] "
or, if you want to save AppleEvents:
XMLRemove {XMLRef:the_root, xpath pattern:" father[ 1 ] / sonny
[ @type = 'ASSET_TYPE' ] "}
-- try to write the resulting XML text back to the file
set eof of POSIX file tempXML to 0
set xmlFileText to XMLDisplayXML the_root
-- display dialog xmlFileText
write xmlFileText to POSIX file tempXML
-- close file on HDD
close access tempXML
You don't need that. Just say:
XMLSave the_root
XMLLib knows what file we're talking about. You forgot a minor
thing: clean-up with XMLClose the_root. Which gives:
-- untested, sorry...
set the_root to XMLRoot (XMLOpen tempxml)
XMLRemove {XMLRef:the_root, xpath pattern:" father[ 1 ] / sonny
[ @type = 'ASSET_TYPE' ] "}
XMLSave the_root
XMLClose the_root
Emmanuel
_______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list (email@hidden
)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list (email@hidden
)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list (email@hidden
)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list (applescript-
email@hidden)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users
This email sent to email@hidden