XMLを解釈してAppleScriptのレコード型のデータに変換するAppleScriptです。
ひとことにXMLといっても、割と書き方にばらつきがあり、1つのルーチンやライブラリで解決できるというものでもない、ということを日々痛感しています。
さまざまな処理方法をおこなうXML解釈プログラムを用意しておいて、かたっぱしから試して適合するものを使っているというところです。本ルーチンで処理できる(解釈しやすい結果を出せる)XMLもあれば、そうでないものもあることでしょう。
また、解釈したXMLのタグについてもそのままではAppleScriptで取り扱えない(スペースを含むとか、特殊文字を含むとか)ものもあり、
XML → NSDictionary → Record
と、AppleScriptのRecordまで変換してしまうと逆に取り扱いにくい場合もあるため、
XML → NSDictionary
と、とどめておいて適宜NSDictionaryからデータを取り出すような処理を行うこともあります。
AppleScript名:XMLをrecordにv2 |
–2015 Shane Stanley & Alex Zavatone — Modified 2016-11-06 by Takaaki Naganoya use AppleScript version "2.4" use scripting additions use framework "Foundation" property dictStack : missing value — stack to hold array of dictionaries property textInProgress : "" — string to collect text as it is found property anError : missing value — if we get an error, store it here set xmlRes to my makeRecordWithXML:(returnData() of me) –> {|character|:{firstName:{|contents|:"Saga"}, lastName:{|contents|:"Norén"}, city:{|contents|:"Malmö"}, partner:{firstName:{|contents|:"Martin"}, lastName:{|contents|:"Rohde"}, city:{|contents|:"København"}, attributes:{approach:"dogged"}}}} on makeRecordWithXML:xmlString — set up properties set my dictStack to current application’s NSMutableArray’s array() — empty mutable array set anEmpty to current application’s NSMutableDictionary’s |dictionary|() (my dictStack)’s addObject:anEmpty — add empty mutable dictionary set my textInProgress to current application’s NSMutableString’s |string|() — empty mutable string — convert XML from string to data set anNSString to current application’s NSString’s stringWithString:xmlString set theData to anNSString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) — initialize an XML parser with the data set theNSXMLParser to current application’s NSXMLParser’s alloc()’s initWithData:theData — set this script to be the parser’s delegate theNSXMLParser’s setDelegate:me — tell it to parse the XML set theResult to theNSXMLParser’s parse() if theResult then — went OK, get first item on stack return ((my dictStack)’s firstObject()) –as record else — error, so return error error (my anError’s localizedDescription() as text) end if end makeRecordWithXML: — this is an XML parser delegate method. Called when new element found on parser:anNSXMLParser didStartElement:elementName namespaceURI:aString qualifiedName:qName attributes:aRecord — store reference to last item on the stack set parentDict to my dictStack’s lastObject() — make new child set childDict to current application’s NSMutableDictionary’s |dictionary|() — if there are attributes, add them as a record with key "attributes" if aRecord’s |count|() > 0 then childDict’s setValue:aRecord forKey:"attributes" end if — see if there’s already an item for this key set existingValue to parentDict’s objectForKey:elementName if existingValue is not missing value then — there is, so if it’s an array, store it… if (existingValue’s isKindOfClass:(current application’s NSMutableArray)) as boolean then set theArray to existingValue else — otherwise create an array and add it set theArray to current application’s NSMutableArray’s arrayWithObject:existingValue parentDict’s setObject:theArray forKey:elementName end if — then add the new dictionary to the array theArray’s addObject:childDict else — add new dictionary directly to the parent parentDict’s setObject:childDict forKey:elementName end if — also add the new dictionary to the end of the stack (my dictStack)’s addObject:childDict end parser:didStartElement:namespaceURI:qualifiedName:attributes: — this is an XML parser delegate method. Called at the end of an element on parser:anNSXMLParser didEndElement:elementName namespaceURI:aString qualifiedName:qName — if any text has been stored, add it as a record with key "contents" if my textInProgress’s |length|() > 0 then set dictInProgress to my dictStack’s lastObject() dictInProgress’s setObject:textInProgress forKey:"contents" — reset textInProgress property for next element set my textInProgress to current application’s NSMutableString’s |string|() end if — remove last item from the stack my dictStack’s removeLastObject() end parser:didEndElement:namespaceURI:qualifiedName: — this is an XML parser delegate method. Called when string is found. May be called repeatedly on parser:anNSXMLParser foundCharacters:aString — only append string if it’s not solely made of space characters (which should be, but aren’t, caught by another delegate method) if (aString’s stringByTrimmingCharactersInSet:(current application’s NSCharacterSet’s whitespaceAndNewlineCharacterSet()))’s |length|() > 0 then (my textInProgress)’s appendString:aString end if end parser:foundCharacters: — this is an XML parser delegate method. Called when there’s an error on parser:anNSXMLParser parseErrorOccurred:anNSError set my anError to anNSError end parser:parseErrorOccurred: on returnData() return "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <rss version=\"2.0\" xmlns:dcterms=\"http://purl.org/dc/terms/\" xmlns:dcndl=\"http://ndl.go.jp/dcndl/terms/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:dcmitype=\"http://purl.org/dc/dcmitype/\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:openSearch=\"http://a9.com/-/spec/opensearchrss/1.0/\" xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"> <channel> <title>Mac使いへの道 – 国立国会図書館サーチ OpenSearch</title> <link>http://iss.ndl.go.jp/api/opensearch?title=Mac%E4%BD%BF%E3%81%84%E3%81%B8%E3%81%AE%E9%81%93</link> <description>Search results for title=Mac使いへの道 </description> <language>ja</language> <openSearch:totalResults>1</openSearch:totalResults> <openSearch:startIndex>1</openSearch:startIndex> <openSearch:itemsPerPage></openSearch:itemsPerPage> <item> <title>Mac使いへの道</title> <link>http://iss.ndl.go.jp/books/R100000002-I000003026578-00</link> <description> <![CDATA[<p>ソフトバンクパブリッシング,4797316489</p> <ul><li>タイトル: Mac使いへの道</li> <li>タイトル(読み): Macツカイ エノ ミチ</li> <li>責任表示: 長野谷隆昌 著,</li> <li>NDC(9): 548.29</li> </ul>]]> </description> <author>長野谷隆昌 著,</author> <category>本</category> <guid isPermaLink=\"true\">http://iss.ndl.go.jp/books/R100000002-I000003026578-00</guid> <pubDate>Thu, 08 May 2003 09:00:00 +0900</pubDate> <dc:title>Mac使いへの道</dc:title> <dcndl:titleTranscription>Macツカイ エノ ミチ</dcndl:titleTranscription> <dc:creator>長野谷隆昌 著</dc:creator> <dc:publisher>ソフトバンクパブリッシング</dc:publisher> <dcterms:issued xsi:type=\"dcterms:W3CDTF\">2001</dcterms:issued> <dc:identifier xsi:type=\"dcndl:ISBN\">4797316489</dc:identifier> <dc:identifier xsi:type=\"dcndl:JPNO\">20206272</dc:identifier> <dc:subject>コンピュータ</dc:subject> <dc:subject xsi:type=\"dcndl:NDLC\">M154</dc:subject> <dc:subject xsi:type=\"dcndl:NDC9\">548.29</dc:subject> <dcterms:description>文献あり</dcterms:description> <rdfs:seeAlso rdf:resource=\"http://id.ndl.go.jp/bib/000003026578\"/> </item> </channel> </rss>" end returnData |
More from my site
(Visited 155 times, 1 visits today)