5

I have a project that has the following XML file (config.xml for a Cordova project) ...

    <?xml version='1.0' encoding='utf-8'?>
    <widget android-versionCode="16" id="com.mycomp.myapp" ios-CFBundleVersion="15" version="1.3.0.b4" windows-packageVersion="1.2.6.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
        <name>My App</name>
        <description>My app description</description>
        <author>mycom.com.au</author>
           ....

All I want to do is read the value of the version attribute (to give me the string 1.3.0.b4) of the root element (widget). Following the example here where it says to use the .@ to get an attribute.

I have the following in my Jenkins file script:

        script {
              def xml = readFile "${env.WORKSPACE}/config.xml"
              def rootNode = new XmlParser().parseText(xml)
              def version = rootNode.@version
              echo 'version is...'
              echo version

But when I run it, I get the following error:

        org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: No such field found: field groovy.util.Node version
        at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.unclassifiedField(SandboxInterceptor.java:425)
        at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetAttribute(SandboxInterceptor.java:436)
        at org.kohsuke.groovy.sandbox.impl.Checker$8.call(Checker.java:370)
        at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetAttribute(Checker.java:375)
        at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getAttribute(SandboxInvoker.java:37)

I have tried rootNode.@version (as above) rootNode[0].@version and rootNode[3].@version but nothing works.

What's wrong with the above?

Edit 1

If I use the following:

def xml = readFile "${env.WORKSPACE}/config.xml"
def rootNode = new XmlParser().parseText(xml)
def version = rootNode.text()
echo 'version is...'
echo version

it prints out My app description which is a bit weird (it jumps down to the description node)

Edit 2

I tried using the following:

 def rootNode = new XmlSlurper().parse("${env.WORKSPACE}/config.xml")
 def version = rootNode.@'version'

but I still get a similar error:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: No such field found: field groovy.util.slurpersupport.NodeChild version
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.unclassifiedField(SandboxInterceptor.java:425)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetAttribute(SandboxInterceptor.java:436)
at org.kohsuke.groovy.sandbox.impl.Checker$8.call(Checker.java:370)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetAttribute(Checker.java:375)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getAttribute(SandboxInvoker.java:37)
at com.cloudbees.groovy.cps.impl.AttributeAccessBlock.rawGet(AttributeAccessBlock.java:20)
at WorkflowScript.run(WorkflowScript:15)
at ___cps.transform___(Native Method)

If I call echo rootNode.text(), once again it seems to just print out the contents of the first 3 tags inside the main ,widget tag, i.e. My AppMy app descriptionmycom.com.au.

halfer
  • 19,824
  • 17
  • 99
  • 186
peterc
  • 6,921
  • 9
  • 65
  • 131
  • There might the some sandbox restricting access to some stuff. With enough rights you can approve some stuff that was blocked, check out the documentation [here](https://jenkins.io/doc/book/managing/script-approval/) – Dominik Gebhart Jun 11 '19 at 18:23
  • @DominikGebhart, yes I did have problems with that, but finally got over them as per the exact doco you reference above. The call to `def rootNode = new XmlParser().parseText(xml)` now works for me (does not throw an exception). It is only when I added the line `def version = rootNode.@version` I got the exception. Eg running `def text = xmlContents.text() + echo 'contents are...' + echo text` did output text for me (just not want I wanted) – peterc Jun 12 '19 at 01:36
  • I might try to reproduce your issue later, however in the past i remember using `XMLSlurper` for something similar, so i checked the difference [here](https://stackoverflow.com/a/7621603/3623345) and it sounds better for your use case (It does not parse whole DOM, just lazy evaluation). Maybe you have more success using it. See [here](https://stackoverflow.com/questions/22769166/groovy-xmlslurper-access-attribute-value-in-root-node), maybe works better? Edit: Also try `def version = rootNode.@'version'` instead of `def version = rootNode.@version` in your code! – Dominik Gebhart Jun 12 '19 at 08:45
  • @DominikGebhart I tried both the above, but still got similar error - added to the main question as EDIT2 so can get formatting. There doesn't seem to be anything wrong with the XML file, so really not sure why it's not working for me? – peterc Jun 12 '19 at 10:41
  • also tried `echo rootNode.parent().text()`. but still seemed to print out the contents of the first 3 inner tags. It seems to be skipping the outer ` ` tag which is the one I am after – peterc Jun 12 '19 at 11:08
  • More test (with the namepace parameters of the constructor, which didn't seem to make any difference ), and it seems it is just skipping the `` tag altogether.... – peterc Jun 12 '19 at 11:34
  • I can reproduce this issue, my current take on it is some issue/error with the script sandbox. Edit: Nevermind disabling the sandbox, i found some workaround, will post as answer. – Dominik Gebhart Jun 12 '19 at 18:58

1 Answers1

11

Edit:

I tested some more in context of being able to also modify the attribute, and found out when using the [] access, the @ selector for attributes actually works. It seems this leads to use different methods under the hood which you can approve in jenkins (getAtand putAt) .

We can simply use

def rootNode = new XmlParser().parseText(xml)
println rootNode['@version']

Original Answer:

There seems some bug regarding the direct access to the attributes with the @ selector on the groovy.util.Node object with the script sandbox.

A workaround is to use the .attributes() method to get the full Map of attributes, and access the value via the key like the following:

def rootNode = new XmlParser().parseText(xml)
println rootNode.attributes()['version']

This will fail the first run and promt you to approve the use of method groovy.util.Node attributes, but once approved will work.

Dominik Gebhart
  • 2,980
  • 1
  • 16
  • 28
  • 1
    Thankyou so much for this answer! This does exactly what I am after, after so many hours of frustration! – peterc Jun 12 '19 at 23:04