Xpath Functions in Logstash

I am needing to use xpath functions like string-join() and concat() to extract what I need from my XML file, however whenever I use these functions I get the following warning in my logstash-plain.log:

[2022-01-21T20:45:34,777][WARN ][logstash.filters.xml ][scap-results]
....XML Parse Error {:exception=>"string-join(/cdf:Benchmark/cdf:TestResult/cdf:rule-result[./cdf:result = 'fail']/(concat(@idref, ' - ', @severity, ' - ', @weight, ' - ', ./cdf:result/text())), codepoints-to-string(10)): javax.xml.transform.TransformerException: Could not find function: string-join", :source=>"message"....

Elastic's xpath filter plugin documentation mentions xpath functions, so it must be possible, however they do not give any examples. I should say I have no problem with the xpath expressions and both my expressions and functions work fine in online xpath testers.

As I understand it, javax.xml implements XPath 1.0, and string-join was introduced in XPath 2.0, so it is not available.

Not sure about concat, it was introduced in 1.x but I do not know if javax.xml supports it.

1 Like

That's the answer to why string-join failed, so thank you! But I still haven't found an example where someone is using a xpath (1.0) function in Logstash. So if you or anyone has an example, that'd be great. I removed the 2.0 functions and just used concat() and still got an XML parse failure:

[2022-01-22T18:01:42,343][WARN ][logstash.filters.xml ][scap-results][7c534c31269189a290afb01983b864ba4a5201d44b94d816ddebe62db807efc0] XML Parse Error {:exception=>"/cdf:Benchmark/cdf:TestResult/cdf:rule-result/(concat(@idref, ' - ', @severity, ' - ', @weight)): javax.xml.transform.TransformerException: A location step was expected following the '/' or '//' token."

It took me ages to experiment with this, and I still cannot get it to work with namespaces but for this XML

<Benchmark id="Windows-XP-Desktop-800-68-1" resolved="1" xml:lang="en" xmlns:cdf="http://checklists.nist.gov/xccdf/1.1">
<TestResult id="Windows-XP-SP-800-68-1" end-time="2007-09-26T05:30:48" test-system="cpe:/a:securitycompany:productname:1.0">
    <rule-result idref="MinimumPasswordAge" time="2007-09-26T05:30:49"/>
</TestResult>
</Benchmark>

the filter

    xml {
        force_array => false
        store_xml => false
        source => "message"
        xpath => { "concat(/Benchmark/TestResult/@id, ' - ', /Benchmark/TestResult/rule-result/@idref)" => "foo" }
        remove_field => [ "message", "event" ]
    }

will produce

       "foo" => "Windows-XP-SP-800-68-1 - MinimumPasswordAge",
1 Like

I got it to work with namespaces, but it seems the key is that the function has to be at the beginning of the xpath (as in your example). It doesn't appear to work inside a path. Anyway, thank you once again for your time and help! At least now I know what is and isn't possible.

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