# Get xml node name

**URL:** <https://discuss.elastic.co/t/get-xml-node-name/269775>\
**Category:** Logstash\
**Created:** [April 10, 2021, 2:16pm UTC](https://discuss.elastic.co/t/get-xml-node-name/269775 "2021-04-10T14:16:34Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Petr\_Vancl\_Hochberge](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/petr_vancl_hochberge/32/79564_2.png) [@Petr\_Vancl\_Hochberge](https://discuss.elastic.co/u/Petr_Vancl_Hochberge)\
**Post date:** [April 10, 2021, 2:16pm UTC](https://discuss.elastic.co/t/get-xml-node-name/269775/1 "2021-04-10T14:16:34Z")

</div>

Hello,  
I am little lost with one problem when parsing xml files to ES with Logstash. Due to unfortunate xml structure which I can't change, I need to get string name of specific nodes. Example of xml structure:

`<Parent>`  
` <FirstName>XXXX</FirstName>`  
` <SecondName>XXXX</SecondName>`  
` <WhateverName>XXXX</ThirdName>`  
`</Parent>`

Names of the "Name fields" may vary and I need to get list of their names to one array field which should be pushed to Elastic like this:

ElasticField = {FirstName, SecondName, WhateverName, etc.}

For text() values I use xml filter and xpath which works great. Is there any easy way, how to do it?

Thank you

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [April 10, 2021, 4:09pm UTC](https://discuss.elastic.co/t/get-xml-node-name/269775/2 "2021-04-10T16:09:56Z")

</div>

The name() function returns the name of the first element it is given. If there is a known limit to the number of name elements you could do

```
    xml {
        source => "message"
        store_xml => false
        xpath => {
            "name(/Parent/*[1])" => "[@metadata][names][0]"
            "name(/Parent/*[2])" => "[@metadata][names][1]"
            "name(/Parent/*[3])" => "[@metadata][names][2]"
            "name(/Parent/*[4])" => "[@metadata][names][3]"
            "name(/Parent/*[5])" => "[@metadata][names][4]"
        }
    }

```

This will create a hash of arrays of arrays

```
    "names" => {
        "1" => [
            [0] "SecondName"
        ],
        "4" => [
            [0] ""
        ],
        ...

```

Why they are out of order (and Ruby hashes are ordered) I have no idea. To convert that to an array you can use a ruby filter. If you do not care about the order then

```
            names = event.get("[@metadata][names]")
            nameList = []
            names.each { |k, v|
                if v[0] != ""
                    nameList << v[0]
                end
            }
            event.set("nameElements", nameList)

```

will get you

```
"nameElements" => [
    [0] "SecondName",
    [1] "FirstName",
    [2] "WhateverName"
],

```

If you do care about order then

```
            nameList = []
            names = event.get("[@metadata][names]")
            (0..4).each { |x|
                if names[x.to_s][0] != ""
                    nameList << names[x.to_s][0]
                end
            }
            event.set("nameElements", nameList)

```

will get you

```
"nameElements" => [
    [0] "FirstName",
    [1] "SecondName",
    [2] "WhateverName"
],

```

I cannot think of a way to deal with an arbitrary number of elements other than setting store\_xml to true and using a ruby filter to extract the element names.

---

<div class="post-metadata">

**Author:** ![Petr\_Vancl\_Hochberge](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/petr_vancl_hochberge/32/79564_2.png) [@Petr\_Vancl\_Hochberge](https://discuss.elastic.co/u/Petr_Vancl_Hochberge)\
**Post date:** [April 11, 2021, 2:26pm UTC](https://discuss.elastic.co/t/get-xml-node-name/269775/3 "2021-04-11T14:26:33Z")

</div>

Thanks, that helped a lot.

However, I have realized that all the nodes I am trying to get their names have the same children structure. Is there any way, how to approach the problem from parent-children perspective?

I am trying to use this:  
`'xpath => {"name(//time//parent::node())" => "NodeNamesArray"}'`

... but it only gets me the first parent node name the parser finds. Is there any other way?

Thank you very much.

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [April 11, 2021, 2:35pm UTC](https://discuss.elastic.co/t/get-xml-node-name/269775/4 "2021-04-11T14:35:51Z")

</div>

> [@Petr\_Vancl\_Hochberge](#):
>
> it only gets me the first parent node name the parser finds

The name function is [documented](https://developer.mozilla.org/en-US/docs/Web/XPath/Functions/name) as returning the name of the first element it is given.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [May 9, 2021, 2:35pm UTC](https://discuss.elastic.co/t/get-xml-node-name/269775/5 "2021-05-09T14:35:53Z")

</div>

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