Closed latenitefilms closed 4 years ago
In theory, yes, the NSXMLDocument object can be written as a block of data to a file, and the NSXMLNode objects allow for changing data.
In practice, I usually found it easier to use third party xml libraries, even lua only ones, for most of what I needed to do, though, hence the reason you see this module in its incomplete state.
OTOH, if you're dealing with particularly large files or ones which include large chunks of encoded data (images, or raw binary chunks) I can understand why an Objective-C based solution would be preferable...
I don't know when I'll have a chance to return to this module (other priorities with Hammerspoon atm and finding time for them is sometimes challenging), so you are welcome to take up the challenge of extending or changing it, if you like.
Awesome, thanks for the fast reply @asmagill ! Any 3rd party XML libraries you'd recommend?
@asmagill - Does hs._asm.xml
in its current form allow for changing data? Any chance you could give me an example of how to edit an node attribute for example?
I thought I had used one for a Roku controlling spoon I hope to submit someday, but it looks like I ended up just writing a simple parser to get at what I specifically needed... I'll have to dig through my archives to see if there were others, though the only other one that immediately jumps to mind was a precursor to the objc module where I was trying to follow the same path that Python does for creating its objc bridge by parsing the framework plists... and that's what led me to start the xml module.
In its current form, you'd need to add methods (or modify existing ones) for changing data. Looking at the apple API docs for NSXMLNode, it looks like you can change the name
, stringValue
, objectValue
, and URI
properties, though I'm not sure how you'd add/remove children, etc.
You may also need to add a method for dumping the whole thing as a string or data block for writing; I can't recall if there is currently a method for outputting the entire file as an XML string or not...
Resources to look at:
Legend, thanks heaps! I'll leave this issue open for now and have a play.
For anyone playing at home, this is what I used to set a string value.
Thanks heaps @asmagill !
/// hs._asm.xml:setStringValue(value) -> string
/// Method
/// Returns the content of the xmlObject as a string value.
///
/// Parameters:
/// * value - The value you want to set the string value to.
///
/// Returns:
/// * the content of the xmlObject as a string value.
static int xml_setStringValue(lua_State *L) {
LuaSkin *skin = [LuaSkin sharedWithState:L] ;
[skin checkArgs:LS_TUSERDATA, USERDATA_TAG, LS_TSTRING, LS_TBREAK] ;
NSXMLNode *obj = [skin toNSObjectAtIndex:1] ;
NSString *value = [skin toNSObjectAtIndex:2] ;
[obj setStringValue:value];
[skin pushNSObject:[obj stringValue]] ;
return 1 ;
}
@asmagill - FYI: for some reason I can't work out how to do a pull request for the above (Classic GitHub Desktop doesn't seem to like the sub-modules in this repository), so if you have a chance, feel free to manually merge this code in.
Can do -- do you have your fork of this repo up somewhere I can see what exact changes you made?
And FYI, I've been moving more and more of these into their own submodules so you only need to pull/edit/fork the ones you actually care about and the code is kept separate... is this one that you'd like me to move to a submodule sooner rather than later?
(The benefit of being a submodule is that you can fork/pull just the ones you want -- you don't have to bother with this "monolithic" list of submodules if you don't want to (or your app has issues with it -- BTW I use SmartGit and my biggest gripe about it and submodules (actually about git in general, as this isn't really a limitation of SmartGit but with how git handles submodules) is that every time I push changes to a submodule, I also have to push the fact that the submodule has changed to this one... so a lot of "updating submodules" entries... but otherwise no complaints)
I literally just added the single function above.
For some reason I was fighting with GitHub, so ended up just copying the code into a branch within CommandPost - see here.
Yes, I think hs._asm.xml
could definitely be moved into it's own sub-module. As far as I can tell it's working awesome for my purposes, so one day I'd love to go back and fill in the documentation gaps, and try and get it ready for sharing back into the Hammerspoon core.
Looking at your specific internal.m
file, you have two similar, but slightly different, functions (and the docs for them probably need tweaking as well)
It's been ages since I've perused the NSXML class docs, so what's the difference and are both required?
/// hs._asm.xml:setStringValue(value) -> string
/// Method
/// Returns the content of the xmlObject as a string value.
///
/// Parameters:
/// * value - The value you want to set the string value to.
///
/// Returns:
/// * the content of the xmlObject as a string value.
static int xml_setStringValue(lua_State *L) {
LuaSkin *skin = [LuaSkin sharedWithState:L] ;
[skin checkArgs:LS_TUSERDATA, USERDATA_TAG, LS_TSTRING, LS_TBREAK] ;
NSXMLNode *obj = [skin toNSObjectAtIndex:1] ;
NSString *value = [skin toNSObjectAtIndex:2] ;
[obj setStringValue:value];
[skin pushNSObject:[obj stringValue]] ;
return 1 ;
}
/// hs._asm.xml:setStringValue(value) -> string
/// Method
/// Returns the content of the xmlObject as a string value.
///
/// Parameters:
/// * value - The value you want to set the string value to.
///
/// Returns:
/// * the content of the xmlObject as a string value.
static int xml_updateStringValue(lua_State *L) {
LuaSkin *skin = [LuaSkin sharedWithState:L] ;
[skin checkArgs:LS_TUSERDATA, USERDATA_TAG, LS_TSTRING, LS_TBREAK] ;
NSXMLElement *obj = [skin toNSObjectAtIndex:1] ;
NSString *value = [skin toNSObjectAtIndex:2] ;
//NSXMLElement *element;
NSXMLNode *node = [[NSXMLNode alloc] initWithKind: NSXMLTextKind];
[node setStringValue:value];
[obj addChild: node];
[skin pushNSObject:[obj stringValue]] ;
return 1 ;
}
On another note, have you and your team had a chance to look at hs.text
yet? I want to try and get back to it after working on axuielement this weekend. I'd like both to be in core before we decide on a final decision whether "to v2 or not to v2".
Oh, sorry, ignore xml_updateStringValue
- I was experimenting with something, but then I later realised that I can use hs._asm.xml:setStringValue(value)
to do everything I needed. So ignore xml_updateStringValue
.
If you want to see how I'm actually using it in action see here.
We're not currently using hs.text
yet. I'll chase up @randomeizer to see if he's had a chance to have a play with it, as to be honest, all the text encoding stuff goes a little bit above my head.
xml moved to submodule at https://github.com/asmagill/hs._asm.xml and new function applied there. Open new issue there if additional changes are required.
@asmagill - Dumb question... is it possible to load a XML document into
hs._asm.xml
, manipulate it in Lua-land, then generate a new XML file? Essentially I just want to "edit" an existing XML file.Here's a test XML.
I'm currently playing around with xml2lua, but not having much luck doing what I want to do.
Any words of wisdom?