Question

I am parsing xml that has many of the same tag. Inside the tag there is a name of a value and then the value. My issue is is that I need to separate those values.

This is an example of the xml I have to parse

  <Event>
  <ipaddress>
  10.0.0.0.
  </ip>

  <sourcesystem>
  somwhere
  </sourcesystem>
  <username>
   fred91
  </username>
   <user>
   <username>
  fred91
   </username>
   <account>
  fredsaccount
   </account>
   <id>
    f2234232
    </id>
   </user>
  ////BELOW IS THE PORTION OF THE XML THAT I AM HAVING ISSUES WITH NOTICE MULTPLE OF THE SAME ELEMENT TAG BUT THE name and values are unique/////
 <event-details>
   <name>Prairie Farms</name>
   <value>Summer Lane Happy Land USA</value>
 </event-details>  
 <event-details>
   <name>House on fire</name>
   <value>ashes</value>
 </event-details>
</Event>

notice that the name of the events change and are not related. If they were related it would be easier to parse. The name is the name of the event and is unique. The value is linked to that unique name. My problem is trying to figure out how to parse out the unique name from the generic element tag and then assign that name the corresponding value. I was told to try to use a collection but I am not sure how to go about doing that. Right now I have it parsing out like this.

sql.query(myQuery, []) { ResultSet rs ->
            while (rs.next()) { 

                  def parsing = new XmlSlurper().parseText(auditDetails)

                        def audit = new Audit()

                        audit.ipAddress = parsing."ip-address".text()
                        audit.sourceSystem = parsing."source-system".text()
                        audit.username = parsing."username".text()



                        parsing."user".each{
                            audit.username = parsing."user"."username".text()
                            audit.account = parsing."user"."account".text()
                            audit.id= parsing."user"."id".text()
                        }


                            /*if (parsing."event-details"."name".text().equals("createdTime")){
                                audit.name = parsing."event-details"."name".text
                                audit.createdTime = parsing."event-details"."value".text()
                            }*/
                            audit.name = parsing."event-details".name?.text()
                            audit.value = parsing."event-details".value?.text()
                        audit.eventDetails = parsing."event-details".text()

With audit being my object and parsing being my xmlslurper. Right now this just gives me all the "name" elements into one string and all there corresponding (In order respectively) values in another string. Like this:

Name: Prairie FarmHouse on fire

Value: Summer Lane Happy Land USAashes

I ultimately need it like

Prairie Farms: Summer Lane Happy Land USA

House On Fire: ashes

I have about 10 different unique names that I know of so far (found by looking at what this query receives with them strung together)

What would I have to write to get it so it picks out the unique event names and links it with its value.

parsing.'event-details'.each{
   if (parsing."event-details"."name".text().equals("createdTime")){
    audit.name = parsing."event-details"."name".text
    audit.createdTime = parsing."event-details"."value".text()
   }
}

^ This was my first thought, going with all the known unique names and going through and assigning a name to a value that way. This would of just linked createdTime with the value and ignore the rest as a test but it didn't even get that far.

Any suggestions or opinions?

Sorry if this is confusing. I find it kind of hard to explain

Thanks for you time!

Était-ce utile?

La solution

Assuming you are using XmlSlurper, try:

def audit = parsing.'event-details'.iterator().collectEntries {
  [ it.name, it.value ]
}

Edit:

Ok, given the xml:

def x = '''<Event>
          |  <ipaddress>10.0.0.0</ipaddress>
          |  <sourcesystem>somwhere</sourcesystem>
          |  <username>fred91</username>
          |  <user>
          |    <username>fred91</username>
          |    <account>fredsaccount</account>
          |    <id>f2234232</id>
          |  </user>
          |  <event-details>
          |    <name>Prairie Farms</name>
          |    <value>Summer Lane Happy Land USA</value>
          |  </event-details>  
          |  <event-details>
          |    <name>House on fire</name>
          |    <value>ashes</value>
          |  </event-details>
          |</Event>'''.stripMargin()

And the Audit class:

@groovy.transform.ToString(includeNames=true)
class Audit {
  String ipAddress, sourceSystem, username, account, id
  Map eventDetails
}

You can do:

def audit = new XmlSlurper().parseText( x ).with { xml ->
  new Audit( ipAddress    : xml.ipaddress,
             sourceSystem : xml.sourcesystem,
             username     : xml.username,
             account      : xml.user.account,
             id           : xml.user.id,
             eventDetails : xml.'event-details'.iterator().collectEntries { [ it.name, it.value ] } )
}

println audit

to print:

Audit(ipAddress:10.0.0.0, sourceSystem:somwhere, username:fred91, account:fredsaccount, id:f2234232, eventDetails:[Prairie Farms:Summer Lane Happy Land USA, House on fire:ashes])

Note:

If you are using Groovy < 1.8.7, then change

             eventDetails : xml.'event-details'.iterator().collectEntries { [ it.name, it.value ] } )

to

             eventDetails : xml.'event-details'.inject( [:] ) { m, e -> m << [ (e.name): e.value ] } )

Autres conseils

Unique keys would help you use map as below:

def audit = [:]
parsing.'event-details'.each{
      def name = parsing.event-details.name?.text() 
      def value = parsing.event-details.value?.text()

      //To make it easy to understand
      audit << [name: value]

      //I would have used
      audit << [(parsing.event-details.name?.text()): parsing.event-details.value?.text()]
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top