Can't get value from hash in XML document

Hello,

I'm struggling with an XML document that I am processing
The part that is annoying me is something like

<Informations>
	<Specs>
		<Dtl>
			<Code>code1</Code>
			<Value>value1</Value>
		</Dtl>
		<Dtl>
			<Code>code2</Code>
			<Value>value2</Value>
		</Dtl>
		<Dtl>
			<Code>code3</Code>
			<Value>value3</Value>
		</Dtl>
	</Specs>
</Informations>

I want to be able to create a new field if I find a specific value in <Code> tag.
For example, if code2 is present I want to create a field containing value2.

The thing is that I don't know how much <Dtl> tags I will have in the document.

With only one <Dtl> I could use a mutate filter like

if [Informations][Specs][Dtl][Code] and [Informations][Specs][Dtl][Code] == "code2" {
    mutate {
      add_field => {"[newField]" => "%{[Informations][Specs][Dtl][Value]}"}
    }
}

However, I may have one but also many more <Dtl> tags.

I have been able to determine that this is a hash type with a ruby filter like

ruby {
    code => "
          case event.get('[Informations][Specs]')
                  when Hash
                    event.set('[Example]', 'This is a hash')
                  end 
    "
}

But I have no idea how to iterate over it and look for a specific code.

If anyone has an idea that would be a greate help !

Thank you

I would expect [Informations][Specs] to be an array, not a hash (unless it contains a single Dtl and you have set force_array to be false).

You could try

ruby {
    code => '
        specs = event.get("[Informations][Specs]")
        if specs.is_a? Array
            specs.each { |x|
                if x["Code"] == "code2"
                    event.set("[newField]", x["Value"])
              end 
            }
        end
    '
}

Hello @Badger thanks for your answer.
I actually set force_array to false in an xml filter you are right, this is why the field is a hash (I didn't think it would have this impact)

xml {
    source => "message"
    store_xml => true
    target => "doc"
    force_array => "false"
 }

(so everything is under the tag doc but I didn't include it in my question.)

In my logstash conf, I am also using the mutate filter to add fields based on other values from my XML document. (and it works fine)

Do you think I should only use a ruby filter and unset force_array to false ?

Only you can decide whether force_array should be true or false, it depends on how it affects all the other elements of the XML.

You could modify the ruby filter to check whether [Informations][Specs] is a hash or an array and process each appropriately.

Thank you Badger, I will let my xml filter as it was because it makes it much more easier to process the documents I will receive.

I will try to add the process for a hash, I guess I just have to check each (key, value)

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.