0

I'm trying to parse an xml-tree. I want to:

  • Print a representation of the path to each item. Is there a smarter way to create the path?
  • Print the name and value of nodes with primaryType="content" (content-nodes)
  • Found a smarter/better approach. Filters? Smarter closures?
    • Can I do it another way to lookahead
  • This example is a simple example of a more complex real-world case I have. Searching for property-elements with primaryType="text"

When running the code below I get:

root/
--folder1/
----folder2/
metadataitem: <- "Wrong" = not what I want
found value: findme

But I want:

root/
--folder1/
----folder2/
------item: <- Without "metadata"  
found value: findme
  • It would be easy to do a stringreplace on "metadata" -> "" but that no good solution.
  • I would also like a smarter solution if you have time.

Thanks in advance!

Example:

def example = '''
<node name="root">
    <property name="primaryType">
        <value>folder</value>
    </property>
    <node name="metadata">
        <property name="primaryType">
            <value>metadata</value>
        </property>
        <property name="other">
            <value>...</value>
        </property>
    </node>
    <node name="folder1">
        <property name="primaryType">
            <value>folder</value>
        </property>
        <node name="metadata">
            <property name="primaryType">
                <value>metadata</value>
            </property>
            <property name="other">
                <value>...</value>
            </property>
        </node>
        <node name="folder2">
            <property name="primaryType">
                <value>folder</value>
            </property>
            <property name="other">
                <value>...</value>
            </property>
            <node name="metadata">
                <property name="primaryType">
                    <value>metadata</value>
                </property>
                <property name="other">
                    <value>...</value>
                </property>
            </node>
            <node name="item">
                <property name="primaryType">
                    <value>content</value>
                </property>
                <property name="text">
                    <value>findme</value>
                </property>
                <property name="other">
                    <value>...</value>
                </property>
            </node>
        </node>
    </node>
</node>
'''

def xml = new XmlSlurper().parseText(example);

def listContent(node,pad) {
    node.node.property.find { it.@name == "primaryType" && it.text() == "content" }.each { 
        it.parent().property.each { property ->
            if(property.@name == "text") {
                println "" + property.parent().@name + ":"// Want: "item". Gets: "metadataitem" due to parent()
                println "found value: " + property.text()
            }
        }
    }
}

def listFolders(node,pad) {
    node.property.find { it.text() == "folder" }.each { property ->
        println "-".multiply(pad) + property.parent().@name + "/"
        listContent(property.parent(),pad) 
    }
    node.children().each { child ->
        listFolders(child, pad+2)
    }
}
listFolders(xml,0)
C-B
  • 33
  • 5

1 Answers1

0

The code you provided (tweaked slightly here)

def listContent( node, pad = 0 ) {
    node.node.property.find { it.@name == "primaryType" && it.text() == "content" }.each { 
        it.parent().property.each { property ->
            if(property.@name == "text") {
                println  "${'-'*pad}${property.parent().@name}:"
                println "found value: " + property.text()
            }
        }
    }
}

def listFolders( node, pad = 0 ) {
    node.property.find { it.text() == "folder" }.each { property ->
        println "${'-'*pad}${property.parent().@name}/"
        listContent(property.parent(),pad + 2) 
    }
    node.children().each { child ->
        listFolders(child, pad+2)
    }
}
listFolders( xml )

Seems to do what you want, and prints

root/
--folder1/
----folder2/
------item:
found value: findme

I can't see how that differs from the requirement in the question?

tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • Thanks for the input. I did know about default values before - nice. Unfortunately, I don't get the same result (for mine nor for your version). I get: `... ------metadataitem: ...` Not `------item:` I'm note sure if this is a OS bug (since you say that you get "item" instead of "metadataitem" as I'm getting). I'm using Groovy Version: 2.1.0 JVM: 1.7.0_17 Vendor: Oracle Corporation OS: Mac OS X – C-B Nov 26 '13 at 23:13
  • If I say it like this: The XML represents a tree-structure of files, where files is all node-objects with primaryType=content. Now I do want to traverse the whole XML-structure for beeing able to serialize the content/items as real files according to the folder-structure defined by the XML. This also gives me other benefits (have use-cases where I only want to find a special item given a specific folder-path for instance, or "give me that path for item named x"). – C-B Nov 26 '13 at 23:28