开发者

How to fetch and parse an XML file using AppleScript?

There's an XML file on some remote server (http://foo/bar.xml):

<?xml version="1.0" encoding="UTF-8"?> 
<foo> 
  bar
</foo>

How can I get the value "bar" using Ap开发者_Python百科pleScript?


Here's what I've done:

set file_tgt to (POSIX path of (path to temporary items)) & "file.xml"
    do shell script "curl -L " & "http://url.com/file.xml" & " -o " & file_tgt
tell application "System Events"
    set file_content to contents of XML file file_tgt
    tell file_content
        set my_value to value of XML element 1
    end tell
end tell

Originally I was using the "URL Access Scripting" app to fetch the file, but since it has been removed in Lion, I switched to pure curl, which works under both Snow Leopard and Lion.


I found this thread which has an example of parsing an XML file with the XML tools available via System Events. Seems pretty convoluted to me though.

There's also this (freeware) scripting addition package for parsing/writing XML. Haven't looked at it, but it might be neat.

Personally, I would save my script as a script bundle, and then I'd make a little php/Ruby/perl/python/whatever script to parse the XML (since I'm just more comfortable with that) in the bundle. Then I'd use AppleScript then pass the XML to the parser script from cURL.

AppleScript:

set scriptPath to POSIX path of (path to me as alias) & "Contents/Resources/parse_xml.rb"
set fooValue to do shell script "curl http://foo/test.xml 2> /dev/null | ruby " & quoted form of scriptPath

parse_xml.rb could be somthing like this (using Ruby as an example):

require "rexml/document"

# load and parse the xml from stdin
xml = STDIN.read
doc = REXML::Document.new(xml)

# output the text of the root element (<foo>) stripped of leading/trailing whitespace
puts doc.root.text.strip

(Ruby and the REXML package should be readily available on any Mac, so it should work anywhere… I believe)

Point is, when the script runs it'll download the XML file with cURL, pass it to the Ruby script, and in the end, fooValue in the AppleScript will be set to "bar".

Of course, if the XML is more complex, you'll need more scripting, or take another look at the other options.

There are probably even more ways of doing it (for instance, you could just do some string manipulation instead of full-on XML parsing, but that's a little brittle of course), but I'll stop here :)


Realizing this is an old question, but here’s one way using the Bing Maps API (note I replaced my API key with XXXXXXXXXX). use do shell script with curl to retrieve the XML, then just walk down the elements until you get to the one you need (you can consolidate all the tells into tell xml element “X” of xml element “y” of xml element…, but this is just easier to follow).

set theXML to make new XML data with properties {name:"Geolocation", text:(do shell script "curl 'http://dev.virtualearth.net/REST/v1/Locations?&q=638%20Brandon%20Town%20Center%20Brandon%20FL%2033511&o=xml&key=XXXXXXXXXX'")}
tell theXML
    tell XML element "Response"
        tell XML element "ResourceSets"
            tell XML element "ResourceSet"
                tell XML element "Resources"
                    tell XML element "Location"
                        tell XML element "Point"
                            set theLatitude to the value of XML element "Latitude"
                            set theLongitude to the value of XML element "Longitude"
                        end tell
                    end tell
                end tell
            end tell
        end tell
    end tell
end tell

EDIT: I suppose I should include the XML I was using for the above:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<Response xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.microsoft.com/search/local/ws/rest/v1\">
  <Copyright>Copyright © 2014 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.</Copyright>
  <BrandLogoUri>http://dev.virtualearth.net/Branding/logo_powered_by.png</BrandLogoUri>
  <StatusCode>200</StatusCode>
  <StatusDescription>OK</StatusDescription>
  <AuthenticationResultCode>ValidCredentials</AuthenticationResultCode>
  <TraceId>06bb657f1ac9466ba00ef45aa55aef3b|BN20130631|02.00.108.1000|BN2SCH020180822, BN2SCH020181444, BN2SCH020181020, BN2SCH030291220, BN2SCH030261523</TraceId>
  <ResourceSets>
    <ResourceSet>
      <EstimatedTotal>1</EstimatedTotal>
      <Resources>
        <Location>
          <Name>638 Brandon Town Center Dr, Brandon, FL 33511</Name>
          <Point>
            <Latitude>27.929752349853516</Latitude>
            <Longitude>-82.326362609863281</Longitude>
          </Point>
          <BoundingBox>
            <SouthLatitude>27.925889632282839</SouthLatitude>
            <WestLongitude>-82.332191670122214</WestLongitude>
            <NorthLatitude>27.933615067424192</NorthLatitude>
            <EastLongitude>-82.320533549604349</EastLongitude>
          </BoundingBox>
          <EntityType>Address</EntityType>
          <Address>
          <AddressLine>638 Brandon Town Center Dr</AddressLine>
          <AdminDistrict>FL</AdminDistrict>
          <AdminDistrict2>Hillsborough Co.</AdminDistrict2>
          <CountryRegion>United States</CountryRegion>
          <FormattedAddress>638 Brandon Town Center Dr, Brandon, FL 33511</FormattedAddress>
          <Locality>Brandon</Locality>
          <PostalCode>33511</PostalCode>
          </Address>
          <Confidence>High</Confidence>
          <MatchCode>Good</MatchCode>
          <GeocodePoint>
            <Latitude>27.929752349853516</Latitude>
            <Longitude>-82.326362609863281</Longitude>
            <CalculationMethod>Parcel</CalculationMethod>
            <UsageType>Display</UsageType>
          </GeocodePoint>
          <GeocodePoint>
            <Latitude>27.929159164428711</Latitude>
            <Longitude>-82.32720947265625</Longitude>
            <CalculationMethod>Interpolation</CalculationMethod>
            <UsageType>Route</UsageType>
          </GeocodePoint>
        </Location>
      </Resources>
    </ResourceSet>
  </ResourceSets>
</Response>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜