1

I have an XMl where an attribute is e.g. model:name.

After upgrading to Grails 2, it fails to extract the attribute using

it.@"model:name".text()

I have read How to read the hyphenated attribute names (Eg. model_name) while parsing xml using XmlSlurper and followed the links too, but nothing points me towards documentation on how to handle coloned attributes.

Final solution for xml:lang attributes: it.attributes()['{http://www.w3.org/XML/1998/namespace}lang']

Community
  • 1
  • 1
mamruoc
  • 847
  • 3
  • 11
  • 21

1 Answers1

2

What you refer to as a "coloned attribute" is actually an attribute that is in a namespace. The default behaviour of XmlSlurper is to ignore namespaces in the sense that when you ask it for a node name without a colon it will find nodes with that local name regardless of namespace. So you may find that simply

it.@name

finds the attribute you're interested in. If that doesn't work then you'll need to call declareNamespace on the object you got back from XmlSlurper, to map a prefix to the namespace URI that corresponds to model: in the XML document (look for the xmlns:model="http://example.com" or whatever in the XML)

def xml = new XmlSlurper().parse(...).declareNamespace(
    model:"http://example.com")

and then model:name should work.

Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
  • In the model:name case, everything worked with just using it.@name. However, I have another XML which have an xml:lang attribute. Trying to match this attribute using it.@lang does not work. None of the XMLs contains namespaces. I have tried it['@xml:lang'] with no luck... – mamruoc Feb 21 '14 at 09:26
  • @mamuroc the `xml` prefix refers to the `http://www.w3.org/XML/1998/namespace` namespace URI by definition, so try mapping that with `declareNamespace` – Ian Roberts Feb 21 '14 at 10:38
  • Hrmf, this is weird. when I do: doc.item.findAll {it."@xml:lang"}.each {println "lang: #" + it."@xml:lang".text() + "#", the output is lang: ##. Obviously, the it."@xml:lang" must exists, because I do get the output lang: ## – mamruoc Feb 21 '14 at 11:20
  • Ok, further debug: doc.item.find {!it.'@xml:lang'.isEmpty()}.each { println "find: " + it.text() } results in empty output. It seems like it either cannot find it.'@xml:lang' or it is empty? – mamruoc Feb 21 '14 at 11:40
  • @mamruoc weird. If I try `new XmlSlurper().parseText('hello')` then I can't find a way to extract the `xml:lang` with `@` but calling `attributes()` to get all the attributes as a `Map` tells me that it is in there (under its namespace qualified name `{http://www.w3.org/XML/1998/namespace}lang`). So `it.attributes()['{http://www.w3.org/XML/1998/namespace}lang']` should give you what you need. – Ian Roberts Feb 21 '14 at 11:42
  • Ai, I didn't think of attributes()! Nice, it works now. Weird that we have to use the whole namespace, looks like some kind of bug. Thank you! – mamruoc Feb 21 '14 at 13:08