Skip to content

NormaliseSpace not always sufficient to prevent whitespace making equivalent docs appear different #34

@electrofelix

Description

@electrofelix

When using this library within vagrant-libvirt in order to help compare XML domain definition sent to libvirt vs what was actually applied by libvirt I discovered that docs that contain different whitespace will sometimes appear not to be equivalent even when using the option NormaliseSpace set to 2, due to the resulting structure may contain a content element while the other doc that did not have the extraneous whitespace will not contain this field at all.

e.g.

<domain xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0' type=''>
  <name/>
  <title/>
  <description/>
  <uuid/>
  <memory/>
  <vcpu>1</vcpu>
  <cpu check="none" mode="host-model">


  </cpu>
  <os>
    <type>hvm</type>
    <kernel/>
    <initrd/>
    <cmdline/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset='utc'/>
  <devices>
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target port='0'/>
    </console>
    <input bus='ps2' type='mouse'/>
    <graphics autoport='yes' keymap='en-us' listen='127.0.0.1' port='-1' type='vnc'/>
    <video>
      <model heads='1' type='cirrus' vram='16384'/>
    </video>
  </devices>
</domain>

vs:

<domain xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0' type=''>
  <name/>
  <title/>
  <description/>
  <uuid/>
  <memory/>
  <vcpu>1</vcpu>
  <cpu check="none" mode="host-model"/>
  <os>
    <type>hvm</type>
    <kernel/>
    <initrd/>
    <cmdline/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset='utc'/>
  <devices>
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target port='0'/>
    </console>
    <input bus='ps2' type='mouse'/>
    <graphics autoport='yes' keymap='en-us' listen='127.0.0.1' port='-1' type='vnc'/>
    <video>
      <model heads='1' type='cirrus' vram='16384'/>
    </video>
  </devices>
</domain>
require 'xmlsimple'

doc1 = <<EOF
<domain xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0' type=''>
  <name/>
  <title/>
  <description/>
  <uuid/>
  <memory/>
  <vcpu>1</vcpu>
  <cpu check="none" mode="host-model">


  </cpu>
  <os>
    <type>hvm</type>
    <kernel/>
    <initrd/>
    <cmdline/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset='utc'/>
  <devices>
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target port='0'/>
    </console>
    <input bus='ps2' type='mouse'/>
    <graphics autoport='yes' keymap='en-us' listen='127.0.0.1' port='-1' type='vnc'/>
    <video>
      <model heads='1' type='cirrus' vram='16384'/>
    </video>
  </devices>
</domain>
EOF

doc2 = <<EOF
<domain xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0' type=''>
  <name/>
  <title/>
  <description/>
  <uuid/>
  <memory/>
  <vcpu>1</vcpu>
  <cpu check="none" mode="host-model"/>
  <os>
    <type>hvm</type>
    <kernel/>
    <initrd/>
    <cmdline/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset='utc'/>
  <devices>
    <serial type='pty'>
      <target port='0'/>
    </serial>
    <console type='pty'>
      <target port='0'/>
    </console>
    <input bus='ps2' type='mouse'/>
    <graphics autoport='yes' keymap='en-us' listen='127.0.0.1' port='-1' type='vnc'/>
    <video>
      <model heads='1' type='cirrus' vram='16384'/>
    </video>
  </devices>
</domain>
EOF

xml1 = XmlSimple.xml_in(doc1, {'NormalizeSpace' => 2})
xml2 = XmlSimple.xml_in(doc2, {'NormalizeSpace' => 2})
xml1 == xml2

will result in false.

I've added some code to vagrant-libvirt to walk the returned structure and remove the content if it's empty since if the whitespace is not relevant there should be no need for the attribute to be defined.
https://github.com/vagrant-libvirt/vagrant-libvirt/blob/439830b6d42758e2607c84d518f61be4235a8213/lib/vagrant-libvirt/util/xml.rb#L25-L43

If I then output the xml1 and input it again, it will have dropped the content field, so I'm wondering if maybe it should be not set at all in the case NormaliseSpace is 2 and after stripping it is empty?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions