Parsing XML to telegraf, possible select several children paths?

Hi, I have xml like this

<?xml version="1.0" encoding="ISO-8859-1"?>
		<name>Channel 3</name>
		<name>Channel 4</name>
		<name>Channel 5</name>

and need select fields only from ch1 and ch2, normally I would use this expression:

/root/ch1/name | /root/ch2/name

But it seems this is not possible in the telegraph config. Currently I can select just ch1. Any advise ?

  interval = "60s"
  name_override = "thermometer"
  tagexclude = ["url", "host"]
  urls = [""]
  data_format = "xml"  
#    timestamp = "root/timeunix"
      devname = "string(/root/devname)"
      alarm = "number(/root/ch1/alarm)"
      sensor = "string(/root/ch1/name)"
	  value = "number(/root/ch1/aval)"
      unit = "string(/root/ch1/unit)"

Hello @CZvacko,
Have you seen this?

What happens when you try:

      sensor = "string(/root/ch2/name)"
     value = "number(/root/ch2/aval)"
      unit = "string(/root/ch2/unit)"


Hi, yes I read that, that’s a nice example, but the child elements use the same name, but in my case the child element name is incremented by +1.

Before asking this question, I tried your suggestion (add such lines under original) and telegraf reject it with below message

[telegraf] Error running agent: Error loading config file C:\Program Files\InfluxData\telegraf.conf: Error parsing data: line 247: table inputs.http.xml.fields is in conflict with table in line 243

It sounds like you want to have one metric for root/ch1 and another metric for root/ch2. When you need a metric per xml node like this, you need to use the metric_selection setting of telegraf’s xml parser. telegraf/ at master · influxdata/telegraf · GitHub

Here’s an example I got working with your data. I’ve switched to a file input instead of http, but that’s not important.

  name_override = "thermometer"
  files = ["community-24806.xml"]
  data_format = "xml"  
    metric_selection = "/root/ch1|/root/ch2"
    # metric_selection = "/root/*[starts-with(name(),'ch')]" # or if you want all nodes starting with ch
    timestamp = "root/timeunix"
      channel = "substring-after(name(), 'ch')"
      sensor = "name"
      alarm = "number(alarm)"
      # sensor = "string(name)" # this is now a tag
      value = "number(aval)"
      unit = "string(unit)"

It produces metrics that look like this

thermometer,channel=1,sensor=Humidity alarm=0i,value=34.2,unit="%RH" 1651266283000000000
thermometer,channel=2,sensor=Temperature alarm=0i,value=20.9,unit="°C" 1651266283000000000

Hi @reimda
Thanks for the support, I didn’t know xpath could be used.
Just a small problem, I still want to store the devname in the db, but now it seems that metric_selection has removed this information. How to solve it ?

Hi @reimda,
as workaround I was trying reconfig device and rename sensor name to include also devname.
But there is a string length limitation, so now I have no way to identify the device. :neutral_face:

Hey @CZvacko,

if you want to store devname as a tag in your example, just specify an absolute path (outside of the selected metric) by adding devname = "/root/devname" to your [inputs.file.xml.tags] section. Similar is possible for fields…

Does that help?

Hi @srebhan, yes, it works! Originaly I used devname = "string(/root/devname)" and after I was advised to use metric_selection, it stopped working. Then I played around with it in many ways, not sure why string() can’t be used for tag selection when it can be used for field selection. I can’t believe it’s that simple :grinning:

I think string() should neither work for field_selection nor for tag_selection as the selection needs to be a node. Anyway, for tags the target-type is clear (string), furthermore, the default-type in XML is string, so you should omit that anyway.

Anyhow, glad it helped. :wink: