xmltodict icon indicating copy to clipboard operation
xmltodict copied to clipboard

force_list with no children

Open antvig opened this issue 7 years ago • 3 comments

Hi, When using force_ list on a node with no children, I would except an empty list but I get a [None]. Is that on purpose or is it a behavior that could be changed?

Thanks

antvig avatar Sep 05 '17 11:09 antvig

What would be the expected output if the node with no children appeared twice, though? E.g.:

 xml = """
        <servers>
          <server></server>
          <server></server>
        </servers>
        """
xmltodict.parse(xml, force_list=('server', ))

I agree that [None, None] is not ideal but at least the list length reflects the number of input nodes.

martinblech avatar Dec 08 '19 09:12 martinblech

<servers>
          <server></server>
          <server></server>
        </servers>

may be converted to

{
  "servers": {
    "server": [
      {
      },
      {
      }
    ]
  }
}

javadev avatar Dec 24 '19 19:12 javadev

'''
        If called with force_list=('interface',), it will produce
        this dictionary:
        {'servers':
          {'server':
            {'name': 'host1',
             'os': 'Linux'},
             'interfaces':
              {'interface':
                [ {'name': 'em0', 'ip_address': '10.0.0.1' } ] } } }
        `force_list` can also be a callable that receives `path`, `key` and
        `value`. This is helpful in cases where the logic that decides whether
        a list should be forced is more complex.
'''

    def push_data(self, item, key, data):
        if self.postprocessor is not None:
            result = self.postprocessor(self.path, key, data)
            if result is None:
                return item
            key, data = result
        if item is None:
            item = self.dict_constructor()
        try:
            value = item[key]
            if isinstance(value, list):
                value.append(data)
            else:
                item[key] = [value, data]
        except KeyError:
            if self._should_force_list(key, data):
                item[key] = [data]
            else:
                item[key] = data
        return item

    def _should_force_list(self, key, value):
        if not self.force_list:
            return False
        if isinstance(self.force_list, bool):
            return self.force_list
        try:
            return key in self.force_list
        except TypeError:
            return self.force_list(self.path[:-1], key, value)

shouldsee avatar Apr 03 '20 04:04 shouldsee