Tuesday, December 12, 2017

#1 2015-12-03 07:51:26 pm

tneison
Member
Registered: 2015-04-03
Posts: 66

Get list of Xpaths to all nodes in an XML

I'm trying to use NSXMLNode's objectsForXQuery:error: to return a list of xPaths for nodes of a certain name OR return a list of Xpaths for all the nodes in the XML.

Option 1 example:

Using this XML:

<project name="markerTest">
    <sequence duration="30s">
        <spine>
            <clip name="test clip 01">
                <marker value="Start"/>
                <marker value="Marker Number 01"/>
                <marker value="Marker Number 02"/>
                <marker value="Marker Number 03"/>
            </clip>
            <clip name="test clip 02">
                <marker value="Marker Number 04"/>
                <marker value="Marker Number 05"/>
                <marker value="Marker Number 06"/>
            </clip>
        </spine>
    </sequence>
</project>


If I just wanted all the nodes with a particular name, I could do:

Applescript:


use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

its getNodes:"/Users/tneison/Desktop/markerTest.fcpxml" forNodesNamed:"marker"

on getNodes:thePath forNodesNamed:targetNode
   set aURL to current application's |NSURL|'s fileURLWithPath:thePath -- make NSURL
   set theXMLDoc to current application's NSXMLDocument's alloc()'s initWithContentsOfURL:aURL options:0 |error|:(missing value) -- make XMLDoc
   set theNodes to theXMLDoc's objectsForXQuery:("//" & targetNode) |error|:(missing value)
   current application's NSLog("%@", theNodes)
end getNodes:forNodesNamed:

Which returns:

"<marker value="Start"></marker>",
    "<marker value="Marker Number 01"></marker>",
    "<marker value="Marker Number 02"></marker>",
    "<marker value="Marker Number 03"></marker>",
    "<marker value="Marker Number 04"></marker>",
    "<marker value="Marker Number 05"></marker>",
    "<marker value="Marker Number 06"></marker>"


It would be great if there were a function that did the same thing BUT instead of returning a list of nodes, it returns a list of Xpaths like this:

/project/sequence/spine/clip/marker
/project/sequence/spine/clip/marker[2]
/project/sequence/spine/clip/marker[3]
/project/sequence/spine/clip/marker[4]
/project/sequence/spine/clip[2]/marker
/project/sequence/spine/clip[2]/marker[2]
/project/sequence/spine/clip[2]/marker[3]


Option 2 example:

Simply return a list of all the xPaths like so:

/project
/project/sequence
/project/sequence/spine
/project/sequence/spine/clip
/project/sequence/spine/clip/marker
/project/sequence/spine/clip/marker[2]
/project/sequence/spine/clip/marker[3]
/project/sequence/spine/clip/marker[4]
/project/sequence/spine/clip[2]
/project/sequence/spine/clip[2]/marker
/project/sequence/spine/clip[2]/marker[2]
/project/sequence/spine/clip[2]/marker[3]


Any Ideas as to how I could accomplish either one of these tasks in ASOC?

Offline

 

#2 2015-12-03 08:18:52 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5199

Re: Get list of Xpaths to all nodes in an XML

Don't confuse what's logged with what you have -- what's logged is just a description. You have the nodes, so you can call the XPath method on them. If you want it as a single string, use something like this:

Applescript:

set theResult to ((theNodes's valueForKey:"XPath")'s componentsJoinedByString:linefeed) as text

It isn't exactly what you asked for because it includes the index for every element:

Applescript:

/project[1]/sequence[1]/spine[1]/clip[1]/marker[1]
/project[1]/sequence[1]/spine[1]/clip[1]/marker[2]
/project[1]/sequence[1]/spine[1]/clip[1]/marker[3]
/project[1]/sequence[1]/spine[1]/clip[1]/marker[4]
/project[1]/sequence[1]/spine[1]/clip[2]/marker[1]
/project[1]/sequence[1]/spine[1]/clip[2]/marker[2]
/project[1]/sequence[1]/spine[1]/clip[2]/marker[3]

But you can get rid of them easily enough:

Applescript:

set theResult to ((theNodes's valueForKey:"XPath")'s componentsJoinedByString:linefeed)
set theResult to (theResult's stringByReplacingOccurrencesOfString:"[1]" withString:"") as text
-->    "/project/sequence/spine/clip/marker
/project/sequence/spine/clip/marker[2]
/project/sequence/spine/clip/marker[3]
/project/sequence/spine/clip/marker[4]
/project/sequence/spine/clip[2]/marker
/project/sequence/spine/clip[2]/marker[2]
/project/sequence/spine/clip[2]/marker[3]"


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#3 2015-12-04 03:51:35 pm

tneison
Member
Registered: 2015-04-03
Posts: 66

Re: Get list of Xpaths to all nodes in an XML

Wow. Thanks. That's pretty easy. I keep forgetting that the array returned is the actual locations in the XMLDocument object. Since that is the case I really don't need to return the xPath. If I want to modify the value of <marker/>, I can simply do this:

Applescript:


use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

its editNodeWithName:"marker" atIndex:0 withAttrNamed:"value" replacementString:"This is a new value" inputPath:"/Users/tneison/Desktop/markerTest.fcpxml" saveResultTo:"/Users/tneison/Desktop/markerTest-RESULT.fcpxml"

on editNodeWithName:targetNode atIndex:|index| withAttrNamed:theAttrName replacementString:newString inputPath:thePath saveResultTo:outputPath
   set aURL to current application's |NSURL|'s fileURLWithPath:thePath -- make NSURL
   set theXMLDoc to current application's NSXMLDocument's alloc()'s initWithContentsOfURL:aURL options:0 |error|:(missing value) -- make XMLDoc
   set theNodes to theXMLDoc's objectsForXQuery:("//" & targetNode) |error|:(missing value)
   set theTag to theNodes's objectAtIndex:|index|
   set theAttr to theTag's attributeForName:theAttrName
   theAttr's setStringValue:newString
   set theXMLData to theXMLDoc's XMLDataWithOptions:(current application's NSXMLNodePrettyPrint)
   theXMLData's writeToFile:outputPath atomically:true
end editNodeWithName:atIndex:withAttrNamed:replacementString:inputPath:saveResultTo:

Offline

 

#4 2015-12-04 05:25:35 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5199

Re: Get list of Xpaths to all nodes in an XML

tneison wrote:

I keep forgetting that the array returned is the actual locations in the XMLDocument object.


That's right. If you want to detach them, you have to use the detach method.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)