xmltodict icon indicating copy to clipboard operation
xmltodict copied to clipboard

attributes not appearing in parse output even with xml_attribs = True

Open stevecoh1 opened this issue 6 years ago • 5 comments

Thanks for a great tool!

I am having a problem with it though. I'm probably doing something wrong but it's not clear to me what. I have an xml document looking something like this

<api>
<cons id="79550" modified_dt="1526652449">
<firstname>Mackenzie</firstname>
...
</cons>
<cons id="79551" modified_dt="1526652549">
<firstname>Joe</firstname>
...
</cons>
<api>

I parse it with this:

xmltodict.parse(apiResult.body, item_depth=2, item_callback=handler, xml_attribs=True)

where apiResult.body contains the xml shown above. But, in spite of the xml_attribs=True, I see no @id or @modified_dt in the output after parsing in the handler, although all the elements in the original do appear.

The handler is coded as follows:

def handler(_, cons):
    print (cons)
    mc = MatchChecker(cons)
    mc.check()
    return True

What might I be doing wrong?

stevecoh1 avatar May 18 '18 17:05 stevecoh1

I don't think I'm doing anything wrong. I think that what is happening is that xml_attribs in my parse call is being overlooked, and that all depths below the requested depth, get xml_attribs true by default. If I specify depth=1, then my depth 2 elements have the attributes show up. Previously, before turning xml_attribs true in my code, all depth 3 elements and below had attributes without my asking for them. So I can sort of make it work by using depth=1, and then have my handler iterate through the list of depth 2 (cons) elements. I don't think that's the way it's supposed to work. The handler should only be handling one element of the desired depth.

stevecoh1 avatar May 18 '18 23:05 stevecoh1

I am having the same problem... it's something not easily resolved with huge XML files that need iterating over a specific level.

ghannum avatar Oct 01 '18 21:10 ghannum

<api>
<cons id="79550" modified_dt="1526652449">
<firstname>Mackenzie</firstname>

</cons>
<cons id="79551" modified_dt="1526652549">
<firstname>Joe</firstname>

</cons>
</api>

may be conveeted to

{
  "api": {
    "cons": [
      {
        "-id": "79550",
        "-modified_dt": "1526652449",
        "firstname": "Mackenzie"
      },
      {
        "-id": "79551",
        "-modified_dt": "1526652549",
        "firstname": "Joe"
      }
    ]
  },
  "#omit-xml-declaration": "yes"
}

javadev avatar Nov 21 '18 05:11 javadev

fyi, I found that I can access the attribute using the path argument in the item_callback function. Try sth like:

def handler(path, cons):
   print(path[1][1]['id'])

billcrook avatar Feb 03 '19 20:02 billcrook

@stevecoh1 A workaround as @billcrook suggestion

def handler(path, cons):
    if path and path[-1]:
        cons.update({'@' + k: v for k, v in path[-1][-1].items()})
    print (cons)
    mc = MatchChecker(cons)
    mc.check()
    return True

timng avatar Feb 20 '20 17:02 timng