diff --git a/tests/cli-test-xml/compare/clone-auto1.xml b/tests/cli-test-xml/compare/clone-auto1.xml
index 8de43fce..1af5374c 100644
--- a/tests/cli-test-xml/compare/clone-auto1.xml
+++ b/tests/cli-test-xml/compare/clone-auto1.xml
@@ -20,10 +20,10 @@
   <devices>
     <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
     <disk type="block" device="floppy">
+      <source dev="/disk-pool/diskvol1-clone"/>
       <target dev="fda" bus="fdc"/>
       <address type="drive" controller="0" bus="0" target="0" unit="0"/>
       <driver type="vmdk"/>
-      <source dev="/disk-pool/diskvol1-clone"/>
     </disk>
     <disk type="block" device="disk">
       <source dev="/disk-pool/diskvol2"/>
@@ -45,14 +45,14 @@
       <address type="drive" controller="0" bus="0" target="0" unit="2"/>
     </disk>
     <disk type="file" device="disk">
+      <source file="/default-pool/default-vol-clone"/>
       <target dev="hda" bus="ide"/>
       <address type="drive" controller="0" bus="0" target="0" unit="0"/>
-      <source file="/default-pool/default-vol-clone"/>
     </disk>
     <disk type="file" device="disk">
+      <source file="/default-pool/testvol2-clone.img"/>
       <target dev="hdb" bus="ide"/>
       <address type="drive" controller="0" bus="0" target="0" unit="1"/>
-      <source file="/default-pool/testvol2-clone.img"/>
     </disk>
     <controller type="scsi" index="0"/>
     <controller type="fdc" index="0"/>
diff --git a/tests/cli-test-xml/compare/clone-auto2.xml b/tests/cli-test-xml/compare/clone-auto2.xml
index e6cb868c..0fe424d1 100644
--- a/tests/cli-test-xml/compare/clone-auto2.xml
+++ b/tests/cli-test-xml/compare/clone-auto2.xml
@@ -20,9 +20,9 @@
   <devices>
     <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
     <disk type="file" device="disk">
+      <source file="/default-pool/newvm.img"/>
       <target dev="hda" bus="ide"/>
       <address type="drive" controller="0" bus="0" target="0" unit="0"/>
-      <source file="/default-pool/newvm.img"/>
     </disk>
     <controller type="ide" index="0"/>
     <interface type="user">
diff --git a/tests/clone-xml/cross-pool-out.xml b/tests/clone-xml/cross-pool-out.xml
index 6035a5da..4fac96b0 100644
--- a/tests/clone-xml/cross-pool-out.xml
+++ b/tests/clone-xml/cross-pool-out.xml
@@ -18,12 +18,12 @@
   <devices>
     <emulator>/usr/bin/qemu-kvm</emulator>
     <disk type="file" device="disk">
-      <target dev="hda" bus="ide"/>
       <source file="/cross-pool/new1.img"/>
+      <target dev="hda" bus="ide"/>
     </disk>
     <disk type="file" device="disk">
-      <target dev="hdb" bus="ide"/>
       <source file="/cross-pool/new2.img"/>
+      <target dev="hdb" bus="ide"/>
     </disk>
     <interface type="network">
       <mac address="22:23:45:67:89:00"/>
diff --git a/tests/clone-xml/empty-disks-out.xml b/tests/clone-xml/empty-disks-out.xml
index fbf079f6..546a9304 100644
--- a/tests/clone-xml/empty-disks-out.xml
+++ b/tests/clone-xml/empty-disks-out.xml
@@ -29,8 +29,8 @@
       <readonly/>
     </disk>
     <disk type="file" device="disk">
-      <target dev="sdb" bus="scsi"/>
       <source file="/tmp/clone2.img"/>
+      <target dev="sdb" bus="scsi"/>
     </disk>
     <interface type="network">
       <mac address="22:23:45:67:89:00"/>
diff --git a/tests/clone-xml/force-out.xml b/tests/clone-xml/force-out.xml
index 1a44f3de..0375f39e 100644
--- a/tests/clone-xml/force-out.xml
+++ b/tests/clone-xml/force-out.xml
@@ -18,8 +18,8 @@
   <devices>
     <emulator>/usr/bin/qemu-kvm</emulator>
     <disk type="file" device="disk">
-      <target dev="hda" bus="ide"/>
       <source file="/default-pool/1234.img"/>
+      <target dev="hda" bus="ide"/>
     </disk>
     <disk type="block" device="floppy">
       <target dev="fdb" bus="fdc"/>
@@ -29,8 +29,8 @@
       <readonly/>
     </disk>
     <disk type="file" device="disk">
-      <target dev="sdb" bus="scsi"/>
       <source file="/tmp/clone2.img"/>
+      <target dev="sdb" bus="scsi"/>
     </disk>
     <interface type="network">
       <mac address="22:23:45:67:89:00"/>
diff --git a/tests/clone-xml/managed-storage-out.xml b/tests/clone-xml/managed-storage-out.xml
index 46653cb2..eeb0bd45 100644
--- a/tests/clone-xml/managed-storage-out.xml
+++ b/tests/clone-xml/managed-storage-out.xml
@@ -18,13 +18,13 @@
   <devices>
     <emulator>/usr/bin/qemu-kvm</emulator>
     <disk type="file" device="disk">
+      <source file="/default-pool/new1.img"/>
       <target dev="hda" bus="ide"/>
       <driver name="qemu" type="vmdk"/>
-      <source file="/default-pool/new1.img"/>
     </disk>
     <disk type="block" device="disk">
-      <target dev="hdb" bus="ide"/>
       <source dev="/disk-pool/new2.img"/>
+      <target dev="hdb" bus="ide"/>
     </disk>
     <interface type="network">
       <mac address="22:23:45:67:89:00"/>
diff --git a/tests/clone-xml/readonly-disks-out.xml b/tests/clone-xml/readonly-disks-out.xml
index 19c22d31..93933feb 100644
--- a/tests/clone-xml/readonly-disks-out.xml
+++ b/tests/clone-xml/readonly-disks-out.xml
@@ -27,8 +27,8 @@
       <readonly/>
     </disk>
     <disk type="file" device="disk">
-      <target dev="sda" bus="scsi"/>
       <source file="/tmp/clone2.img"/>
+      <target dev="sda" bus="scsi"/>
     </disk>
     <disk type="block" device="cdrom">
       <target dev="sdb" bus="scsi"/>
diff --git a/tests/clone-xml/skip-out.xml b/tests/clone-xml/skip-out.xml
index 90319888..baa41e49 100644
--- a/tests/clone-xml/skip-out.xml
+++ b/tests/clone-xml/skip-out.xml
@@ -29,8 +29,8 @@
       <readonly/>
     </disk>
     <disk type="file" device="disk">
-      <target dev="sdb" bus="scsi"/>
       <source file="/default-pool/1234.img"/>
+      <target dev="sdb" bus="scsi"/>
     </disk>
     <interface type="network">
       <mac address="22:23:45:67:89:00"/>
diff --git a/tests/nodedev-xml/devxml/pcidev.xml b/tests/nodedev-xml/devxml/pcidev.xml
index 2f3dd5da..dca82993 100644
--- a/tests/nodedev-xml/devxml/pcidev.xml
+++ b/tests/nodedev-xml/devxml/pcidev.xml
@@ -1,5 +1,6 @@
-    <hostdev mode="subsystem" type="pci" managed="yes">
-      <source>
-        <address domain="0" bus="21" slot="0" function="4"/>
-      </source>
-    </hostdev>
+<hostdev mode="subsystem" type="pci" managed="yes">
+  <source>
+    <address domain="0" bus="21" slot="0" function="4"/>
+  </source>
+</hostdev>
+
diff --git a/tests/nodedev-xml/devxml/usbdev1.xml b/tests/nodedev-xml/devxml/usbdev1.xml
index eeb90f1f..44712453 100644
--- a/tests/nodedev-xml/devxml/usbdev1.xml
+++ b/tests/nodedev-xml/devxml/usbdev1.xml
@@ -1,6 +1,7 @@
-    <hostdev mode="subsystem" type="usb" managed="yes">
-      <source>
-        <vendor id="0x0781"/>
-        <product id="0x5151"/>
-      </source>
-    </hostdev>
+<hostdev mode="subsystem" type="usb" managed="yes">
+  <source>
+    <vendor id="0x0781"/>
+    <product id="0x5151"/>
+  </source>
+</hostdev>
+
diff --git a/tests/nodedev-xml/devxml/usbdev2.xml b/tests/nodedev-xml/devxml/usbdev2.xml
index 522f7dae..73364b56 100644
--- a/tests/nodedev-xml/devxml/usbdev2.xml
+++ b/tests/nodedev-xml/devxml/usbdev2.xml
@@ -1,7 +1,8 @@
-    <hostdev mode="subsystem" type="usb" managed="yes">
-      <source>
-        <vendor id="0x0781"/>
-        <product id="0x5151"/>
-        <address bus="1" device="4"/>
-      </source>
-    </hostdev>
+<hostdev mode="subsystem" type="usb" managed="yes">
+  <source>
+    <vendor id="0x0781"/>
+    <product id="0x5151"/>
+    <address bus="1" device="4"/>
+  </source>
+</hostdev>
+
diff --git a/tests/xmlconfig-xml/boot-cpuset.xml b/tests/xmlconfig-xml/boot-cpuset.xml
index ac4627ad..c8f35b19 100644
--- a/tests/xmlconfig-xml/boot-cpuset.xml
+++ b/tests/xmlconfig-xml/boot-cpuset.xml
@@ -13,7 +13,7 @@
     <acpi/>
     <apic/>
   </features>
-  <cpu match="minimum" mode="custom">
+  <cpu mode="custom" match="minimum">
     <model>footest</model>
     <vendor>Intel</vendor>
     <topology sockets="4" cores="5" threads="2"/>
diff --git a/tests/xmlconfig-xml/rhel6-kvm-stage1.xml b/tests/xmlconfig-xml/rhel6-kvm-stage1.xml
index 19c1b946..f3a49b7c 100644
--- a/tests/xmlconfig-xml/rhel6-kvm-stage1.xml
+++ b/tests/xmlconfig-xml/rhel6-kvm-stage1.xml
@@ -6,8 +6,8 @@
   <vcpu>5</vcpu>
   <os>
     <type arch="i686">hvm</type>
-    <kernel>kernel</kernel>
-    <initrd>initrd</initrd>
+    <kernel>./virtinst-vmlinuz.</kernel>
+    <initrd>./virtinst-initrd.img.</initrd>
     <cmdline>method=tests/cli-test-xml/fakerhel6tree</cmdline>
   </os>
   <features>
diff --git a/tests/xmlconfig.py b/tests/xmlconfig.py
index 774936ea..74a62921 100644
--- a/tests/xmlconfig.py
+++ b/tests/xmlconfig.py
@@ -18,8 +18,6 @@ import unittest
 import os
 import logging
 
-import urlgrabber.progress as progress
-
 import virtinst
 from virtinst import VirtualDisk
 from virtinst import VirtualAudio
@@ -67,7 +65,7 @@ class TestXMLConfig(unittest.TestCase):
                  do_create=True):
         filename = filebase and build_xmlfile(filebase) or None
 
-        guest._prepare_install(progress.BaseMeter())
+        guest._prepare_install(None)
         try:
             actualXML = guest.get_install_xml(install=do_install,
                                               disk_boot=do_disk_boot)
@@ -93,11 +91,6 @@ class TestXMLConfig(unittest.TestCase):
             guest.start_install(consolecb, meter, removeOld, wait)
             guest.domain.destroy()
 
-            # Replace kernel/initrd with known info
-            if guest.installer._install_kernel:
-                guest.installer._install_kernel = "kernel"
-                guest.installer._install_initrd = "initrd"
-
             xmlinst = guest.get_install_xml(True, False)
             xmlboot = guest.get_install_xml(False, False)
             xmlcont = guest.get_install_xml(True, True)
@@ -320,10 +313,6 @@ class TestXMLConfig(unittest.TestCase):
 
         # Call get_xml_config sets first round of defaults w/o os_variant set
         g.get_install_xml(do_install)
-        g._prepare_install(None)
-        g.get_install_xml(do_install)
-        g._prepare_install(None)
-        g.get_install_xml(do_install)
 
         g.os_variant = "fedora11"
         self._compare(g, "install-f11", do_install)
@@ -992,19 +981,19 @@ class TestXMLConfig(unittest.TestCase):
             dev3.macaddr = "22:22:33:44:55:68"
 
             utils.diff_compare(dev1.get_xml_config(), None,
-                               "    <interface type=\"bridge\">\n"
-                               "      <source bridge=\"bzz0\"/>\n"
-                               "      <mac address=\"22:22:33:44:55:66\"/>\n"
-                               "    </interface>")
+                               "<interface type=\"bridge\">\n"
+                               "  <source bridge=\"bzz0\"/>\n"
+                               "  <mac address=\"22:22:33:44:55:66\"/>\n"
+                               "</interface>\n")
             utils.diff_compare(dev2.get_xml_config(), None,
                                "<interface type=\"bridge\">\n"
-                               "      <mac address=\"22:22:33:44:55:67\"/>\n"
-                               "      <source bridge=\"foobr0\"/>\n"
-                               "    </interface>\n")
+                               "  <source bridge=\"foobr0\"/>\n"
+                               "  <mac address=\"22:22:33:44:55:67\"/>\n"
+                               "</interface>\n")
             utils.diff_compare(dev3.get_xml_config(), None,
                                "<interface type=\"bridge\">\n"
-                               "      <mac address=\"22:22:33:44:55:68\"/>\n"
-                               "    </interface>\n")
+                               "  <mac address=\"22:22:33:44:55:68\"/>\n"
+                               "</interface>\n")
         finally:
             if util and origfunc:
                 util.default_bridge = origfunc
diff --git a/tests/xmlparse-xml/add-devices-out.xml b/tests/xmlparse-xml/add-devices-out.xml
index 114088a5..24d48bcb 100644
--- a/tests/xmlparse-xml/add-devices-out.xml
+++ b/tests/xmlparse-xml/add-devices-out.xml
@@ -38,11 +38,11 @@
     </interface>
     <graphics type="sdl" display=":3.4" xauth="/tmp/.Xauthority"/>
     <console type="pty"/>
-    <watchdog model="i6300esb" action="reset"/>
     <interface type="network">
       <source network="default"/>
       <mac address="1A:2A:3A:4A:5A:6A"/>
     </interface>
+    <watchdog model="i6300esb" action="reset"/>
   </devices>
   <seclabel type="static" model="selinux">
     <label>foolabel</label>
diff --git a/tests/xmlparse-xml/change-boot-multi-out.xml b/tests/xmlparse-xml/change-boot-multi-out.xml
index a374cb3f..1d1a1596 100644
--- a/tests/xmlparse-xml/change-boot-multi-out.xml
+++ b/tests/xmlparse-xml/change-boot-multi-out.xml
@@ -7,10 +7,10 @@
     <type arch="i686">hvm</type>
     <loader>/usr/lib/xen/boot/hvmloader</loader>
     <bootmenu enable="yes"/>
-    <boot dev="cdrom"/>
     <kernel>foo.img</kernel>
     <initrd>bar.img</initrd>
     <cmdline>ks=foo.ks</cmdline>
+    <boot dev="cdrom"/>
   </os>
   <features>
     <acpi/><apic/>
diff --git a/tests/xmlparse-xml/change-chars-out.xml b/tests/xmlparse-xml/change-chars-out.xml
index 9f94987a..c94c3ad4 100644
--- a/tests/xmlparse-xml/change-chars-out.xml
+++ b/tests/xmlparse-xml/change-chars-out.xml
@@ -37,8 +37,8 @@
     </parallel>
     <console type="pty"/>
     <console type="file">
-      <target type="virtio"/>
       <source path="/root/foo"/>
+      <target type="virtio"/>
     </console>
     <channel type="pty">
       <target type="virtio" name="test.changed"/>
diff --git a/tests/xmlparse-xml/change-disk-out.xml b/tests/xmlparse-xml/change-disk-out.xml
index 7f60efaa..6702201d 100644
--- a/tests/xmlparse-xml/change-disk-out.xml
+++ b/tests/xmlparse-xml/change-disk-out.xml
@@ -21,8 +21,8 @@
     <disk type="block" device="disk">
       <target dev="hda" bus="ide"/>
       <serial>frob</serial>
-      <source dev="/dev/loop0"/>
       <driver name="test" type="raw"/>
+      <source dev="/dev/loop0"/>
     </disk>
     <disk type="block" device="disk">
       <source dev="/dev/loop0"/>
@@ -50,9 +50,9 @@
         <total_iops_sec>5</total_iops_sec>
         <total_bytes_sec>6</total_bytes_sec>
       </iotune>
+      <driver cache="writeback" io="native"/>
       <source file="/default-pool/default-vol"/>
       <shareable/>
-      <driver cache="writeback" io="native"/>
     </disk>
     <disk type="block" device="floppy">
       <driver name="phy" cache="none"/>
diff --git a/tests/xmlparse-xml/change-guest-out.xml b/tests/xmlparse-xml/change-guest-out.xml
index 6a211e05..eb3dd42a 100644
--- a/tests/xmlparse-xml/change-guest-out.xml
+++ b/tests/xmlparse-xml/change-guest-out.xml
@@ -6,12 +6,11 @@
   <os>
     <type machine="pc-0.11">xen</type>
     <loader>/foo/loader</loader>
-    <init>/sbin/init</init>
     <boot dev="fd"/>
+    <init>/sbin/init</init>
     <bootmenu enable="no"/>
   </os>
-  <features>
-    <apic/>
+  <features><apic/>
   </features>
   <numatune>
     <memory nodeset="2,4,6"/>
diff --git a/tests/xmlparse-xml/change-minimal-guest-out.xml b/tests/xmlparse-xml/change-minimal-guest-out.xml
index 1821aaa9..c0bebc2b 100644
--- a/tests/xmlparse-xml/change-minimal-guest-out.xml
+++ b/tests/xmlparse-xml/change-minimal-guest-out.xml
@@ -19,12 +19,12 @@
     <acpi/>
   </features>
   <clock offset="utc"/>
-  <seclabel model="testSecurity" type="static">
+  <seclabel type="static" model="testSecurity">
     <label>frob</label>
   </seclabel>
   <cpu mode="custom" match="exact">
     <model>foobar</model>
-    <topology cores="4" sockets="1" threads="1"/>
+    <topology sockets="1" cores="4" threads="1"/>
     <feature name="x2apic" policy="forbid"/>
   </cpu>
 </domain>
diff --git a/tests/xmlparse-xml/change-nics-out.xml b/tests/xmlparse-xml/change-nics-out.xml
index cf978c4e..8ee098e5 100644
--- a/tests/xmlparse-xml/change-nics-out.xml
+++ b/tests/xmlparse-xml/change-nics-out.xml
@@ -20,13 +20,13 @@
     <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
     <interface type="user">
       <mac address="AA:AA:AA:AA:AA:AA"/>
-      <model type="testmodel"/>
       <source bridge="br0" network="route"/>
+      <model type="testmodel"/>
     </interface>
     <interface type="bridge">
+      <source bridge="newbr0"/>
       <mac address="22:22:33:44:55:66"/>
       <model type="virtio"/>
-      <source bridge="newbr0"/>
     </interface>
     <interface type="bridge">
       <source bridge="newfoo0" network="default"/>
diff --git a/tests/xmlparse.py b/tests/xmlparse.py
index bbca0950..ef7e7e88 100644
--- a/tests/xmlparse.py
+++ b/tests/xmlparse.py
@@ -744,8 +744,8 @@ class XMLParseTest(unittest.TestCase):
         adddev.macaddr = "1A:2A:3A:4A:5A:6A"
 
         guest.add_device(virtinst.VirtualWatchdog(conn))
-        guest.add_device(adddev)
 
+        guest.add_device(adddev)
         guest.remove_device(adddev)
         guest.add_device(adddev)
 
diff --git a/virtinst/CPU.py b/virtinst/CPU.py
index 0c9456a4..af3744e4 100644
--- a/virtinst/CPU.py
+++ b/virtinst/CPU.py
@@ -70,7 +70,7 @@ class CPU(XMLBuilder):
     def _parsexml(self, xml, node):
         XMLBuilder._parsexml(self, xml, node)
 
-        for node in self._xml_node.children:
+        for node in self._xml_node.children or []:
             if node.name != "feature":
                 continue
             if not node.prop("name"):
diff --git a/virtinst/Guest.py b/virtinst/Guest.py
index 5026f258..fa31f639 100644
--- a/virtinst/Guest.py
+++ b/virtinst/Guest.py
@@ -337,12 +337,9 @@ class Guest(XMLBuilder):
         @param dev: VirtualDevice instance to attach to guest
         @param set_defaults: Whether to set defaults for the device
         """
-        if self._is_parse():
-            self._add_child("./devices", dev)
-
         self._track_device(dev)
-        if self._is_parse():
-            self._recalculate_device_xpaths()
+        self._add_child("./devices", dev)
+        self._recalculate_device_xpaths()
 
         if set_defaults:
             origdev = self._devices
@@ -365,7 +362,6 @@ class Guest(XMLBuilder):
                         VirtualDevice.virtual_device_types)
         """
         devlist = self._dev_build_list(devtype)
-        devlist.extend(self._install_devices)
         return self._dev_build_list(devtype, devlist)
 
     def get_all_devices(self):
@@ -384,7 +380,7 @@ class Guest(XMLBuilder):
         @param dev: VirtualDevice instance
         """
         found = False
-        for devlist in [self._devices, self._install_devices]:
+        for devlist in [self._devices]:
             if found:
                 break
 
@@ -396,11 +392,13 @@ class Guest(XMLBuilder):
         if not found:
             raise ValueError(_("Did not find device %s") % str(dev))
 
-        if self._is_parse():
-            xpath = dev.get_root_xpath()
-            if xpath:
-                self._remove_child_xpath(xpath)
-            self._recalculate_device_xpaths()
+        xpath = dev.get_root_xpath()
+        xml = dev.get_xml_config()
+        dev.set_root_xpath(None)
+        dev._parsexml(xml, None)
+        if xpath:
+            self._remove_child_xpath(xpath)
+        self._recalculate_device_xpaths()
 
 
     ################################
@@ -410,7 +408,7 @@ class Guest(XMLBuilder):
     def _parsexml(self, xml, node):
         XMLBuilder._parsexml(self, xml, node)
 
-        for node in self._xml_node.children:
+        for node in self._xml_node.children or []:
             if node.name != "devices":
                 continue
 
@@ -455,6 +453,8 @@ class Guest(XMLBuilder):
     ############################
 
     def _prepare_install(self, meter, dry=False):
+        for dev in self._install_devices:
+            self.remove_device(dev)
         self._install_devices = []
         ignore = dry
 
@@ -464,6 +464,7 @@ class Guest(XMLBuilder):
 
         # Initialize install device list
         for dev in self.installer.install_devices:
+            self.add_device(dev)
             self._install_devices.append(dev)
 
     def _cleanup_install(self):
diff --git a/virtinst/VirtualCharDevice.py b/virtinst/VirtualCharDevice.py
index fdcc24fa..3895b35a 100644
--- a/virtinst/VirtualCharDevice.py
+++ b/virtinst/VirtualCharDevice.py
@@ -139,7 +139,7 @@ class _VirtualCharDevice(VirtualDevice):
         return hasattr(self, propname)
 
 
-    _XML_PROP_ORDER = ["type",
+    _XML_PROP_ORDER = ["type", "_has_mode_bind", "_has_mode_connect",
                        "bind_host", "bind_port",
                        "source_mode", "source_path",
                        "source_host", "source_port",
diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py
index fc6b7235..3118b6af 100644
--- a/virtinst/VirtualDisk.py
+++ b/virtinst/VirtualDisk.py
@@ -607,9 +607,12 @@ class VirtualDisk(VirtualDevice):
             #
             # This will update the XML value with the newly determined
             # default value, but it won't edit propstore. This means
+            if self.is_build():
+                return
             prop = self.all_xml_props()[propname]
-            val = getattr(prop, "_default_cb")(self)
-            prop.setter(self, val, call_fset=False)
+            candefault, val = getattr(prop, "_default_get_value")(self)
+            if candefault:
+                getattr(prop, "_set_xml")(self, val)
 
         refresh_prop_xml("type")
         refresh_prop_xml("driver_name")
diff --git a/virtinst/xmlbuilder.py b/virtinst/xmlbuilder.py
index b4f8e338..bad71c83 100644
--- a/virtinst/xmlbuilder.py
+++ b/virtinst/xmlbuilder.py
@@ -351,19 +351,6 @@ class XMLProperty(property):
         return xmlbuilder.fix_relative_xpath(ret)
 
 
-    def _convert_value_for_setter(self, xmlbuilder):
-        # Convert from API value to XML value
-        val = self._nonxml_fget(xmlbuilder)
-        if self._default_name and val == self._default_name:
-            val = self._default_cb(xmlbuilder)
-        elif self._is_yesno:
-            if val is not None:
-                val = bool(val) and "yes" or "no"
-
-        if self._convert_value_for_setter_cb:
-            val = self._convert_value_for_setter_cb(xmlbuilder, val)
-        return val
-
     def _build_node_list(self, xmlbuilder, xpath):
         """
         Build list of nodes that the passed xpaths reference
@@ -408,11 +395,37 @@ class XMLProperty(property):
             ret = val
         return ret
 
+    def _convert_set_value(self, xmlbuilder, val):
+        if self._default_name and val == self._default_name:
+            val = self._default_cb(xmlbuilder)
+        elif self._is_yesno:
+            if val is not None:
+                val = bool(val) and "yes" or "no"
+
+        if self._convert_value_for_setter_cb:
+            val = self._convert_value_for_setter_cb(xmlbuilder, val)
+        return val
+
     def _prop_is_unset(self, xmlbuilder):
         propstore = getattr(xmlbuilder, "_propstore")
         propname = self._findpropname(xmlbuilder)
         return (propname not in propstore)
 
+    def _default_get_value(self, xmlbuilder):
+        """
+        Return (can use default, default value)
+        """
+        ret = (False, -1)
+        if not self._prop_is_unset(xmlbuilder):
+            return ret
+        if not self._default_cb:
+            return ret
+
+        if self._default_name:
+            return (True, self._default_name)
+        return (True, self._default_cb(xmlbuilder))
+
+
     def _set_default(self, xmlbuilder):
         """
         Encode the property default into the XML and propstore, but
@@ -422,13 +435,10 @@ class XMLProperty(property):
         This is called during the get_xml_config process and shouldn't
         be called from outside this file.
         """
-        if not self._prop_is_unset(xmlbuilder):
+        candefault, val = self._default_get_value(xmlbuilder)
+        if not candefault:
             return
-        if not self._default_cb:
-            return
-        if self._default_cb(xmlbuilder) is None:
-            return
-        self.setter(xmlbuilder, self.getter(xmlbuilder), validate=False)
+        self.setter(xmlbuilder, val, validate=False)
 
     def _nonxml_fset(self, xmlbuilder, val):
         """
@@ -453,17 +463,17 @@ class XMLProperty(property):
         The flip side to nonxml_fset, fetch the value from
         XMLBuilder._propstore
         """
+        candefault, val = self._default_get_value(xmlbuilder)
+        if candefault:
+            return val
+
         propstore = getattr(xmlbuilder, "_propstore")
         propname = self._findpropname(xmlbuilder)
-        unset = (propname not in propstore)
-        if unset and self._default_cb:
-            if self._default_name:
-                return self._default_name
-            return self._default_cb(xmlbuilder)
         return propstore.get(propname, None)
 
     def _clear(self, xmlbuilder):
         self.setter(xmlbuilder, None)
+        self._set_xml(xmlbuilder, None)
 
 
     ##################################
@@ -471,33 +481,38 @@ class XMLProperty(property):
     ##################################
 
     def getter(self, xmlbuilder):
-        if xmlbuilder._xml_ctx is None:
-            fgetval = self._nonxml_fget(xmlbuilder)
-            return self._convert_get_value(fgetval)
+        if self._prop_is_unset(xmlbuilder) and not xmlbuilder.is_build():
+            val = self._get_xml(xmlbuilder)
+        else:
+            val = self._nonxml_fget(xmlbuilder)
+        ret = self._convert_get_value(val)
+        return ret
 
+    def _get_xml(self, xmlbuilder):
         xpath = self._xpath_for_getter(xmlbuilder)
         node = _get_xpath_node(xmlbuilder._xml_ctx, xpath)
-
         if not node:
-            return self._convert_get_value(None)
+            return None
 
         content = node.content
         if self._is_bool:
             content = True
-        return self._convert_get_value(content)
+        return content
 
-    def setter(self, xmlbuilder, val, call_fset=True, validate=True):
-        if call_fset:
-            if validate and self._validate_cb:
-                self._validate_cb(xmlbuilder, val)
-            self._nonxml_fset(xmlbuilder, val)
+    def setter(self, xmlbuilder, val, validate=True):
+        if validate and self._validate_cb:
+            self._validate_cb(xmlbuilder, val)
+        self._nonxml_fset(xmlbuilder,
+                          self._convert_set_value(xmlbuilder, val))
 
-        root_node = getattr(xmlbuilder, "_xml_node")
-        if root_node is None:
+        if xmlbuilder.is_build():
             return
+        self._convert_set_value(xmlbuilder, val)
 
+    def _set_xml(self, xmlbuilder, setval, root_node=None):
+        if root_node is None:
+            root_node = xmlbuilder._xml_node
         xpath = self._xpath_for_setter(xmlbuilder)
-        setval = self._convert_value_for_setter(xmlbuilder)
         node = _get_xpath_node(xmlbuilder._xml_ctx, xpath)
         clearlist = self._build_clear_list(xmlbuilder, node)
 
@@ -562,8 +577,11 @@ class XMLBuilder(object):
         self._propstore = {}
         self._proporder = []
 
-        if parsexml or parsexmlnode:
-            self._parsexml(parsexml, parsexmlnode)
+        self._is_build = False
+        if not (parsexml or parsexmlnode):
+            parsexml = self._make_xml_stub()
+            self._is_build = True
+        self._parsexml(parsexml, parsexmlnode)
 
 
     ##############
@@ -580,7 +598,8 @@ class XMLBuilder(object):
         self._parsexml(xml, None)
 
     def set_root_xpath(self, xpath):
-        self._xml_root_xpath = xpath
+        self._xml_root_xpath = xpath or ""
+        self._xml_dump_xpath = xpath or self._XML_ROOT_XPATH
         xmlprops = self.all_xml_props()
 
         for propname in self._XML_PROP_ORDER:
@@ -608,30 +627,12 @@ class XMLBuilder(object):
         for prop in self.all_xml_props().values():
             prop._clear(self)
 
-    def _do_get_xml_config(self):
-        """
-        Construct and return object xml
-
-        @return: object xml representation as a string
-        @rtype: str
-        """
-        if self._xml_ctx:
-            node = _get_xpath_node(self._xml_ctx, self._xml_dump_xpath)
-            if not node:
-                ret = ""
-            else:
-                ret = _sanitize_libxml_xml(node.serialize())
-        else:
-            xmlstub = self._make_xml_stub()
-            if xmlstub is None:
-                return None
-
-            ret = self._add_parse_bits(xmlstub)
-            if ret == xmlstub:
-                ret = ""
-
-        if ret and self._xml_root_name == "domain" and not ret.endswith("\n"):
-            ret += "\n"
+    def all_xml_props(self):
+        ret = {}
+        for c in reversed(type.mro(self.__class__)[:-1]):
+            for key, val in c.__dict__.items():
+                if val.__class__ is XMLProperty:
+                    ret[key] = val
         return ret
 
 
@@ -639,8 +640,8 @@ class XMLBuilder(object):
     # Internal helper API #
     #######################
 
-    def _is_parse(self):
-        return bool(self._xml_node or self._xml_ctx)
+    def is_build(self):
+        return bool(self._is_build)
 
 
     ###################
@@ -663,6 +664,36 @@ class XMLBuilder(object):
     # Internal XML parsers #
     ########################
 
+    def _get_node_xml(self, ctx=None):
+        if ctx is None:
+            ctx = self._xml_ctx
+
+        node = _get_xpath_node(ctx, self._xml_dump_xpath)
+        if not node:
+            return ""
+        return _sanitize_libxml_xml(node.serialize())
+
+    def _do_get_xml_config(self):
+        xmlstub = self._make_xml_stub()
+
+        try:
+            node = None
+            ctx = None
+            if self.is_build():
+                node = self._xml_node.docCopyNodeList(self._xml_node.doc)
+                ctx = self._make_xml_context(node)
+            ret = self._add_parse_bits(node, ctx)
+        finally:
+            if node:
+                node.freeNode()
+
+        if ret == xmlstub:
+            ret = ""
+
+        if ret and self._xml_root_name == "domain" and not ret.endswith("\n"):
+            ret += "\n"
+        return ret
+
     def _make_xml_stub(self):
         return _indent("<%s/>" % (self._xml_root_name), self._xml_indent)
 
@@ -671,26 +702,30 @@ class XMLBuilder(object):
         Insert the passed XMLBuilder object into our XML document at the
         specified path
         """
-        dev.set_new_xml(dev.get_xml_config())
-        newnode = dev._xml_node
-        ret = _build_xpath_node(self._xml_ctx, parent_xpath, newnode)
-        return ret
+        if not dev.is_build():
+            newnode = libxml2.parseDoc(dev.get_xml_config()).children
+            _build_xpath_node(self._xml_ctx, parent_xpath, newnode)
+        dev._parsexml(None, self._xml_node)
 
     def _remove_child_xpath(self, xpath):
         _remove_xpath_node(self._xml_ctx, xpath, dofree=False)
         self._set_xml_context()
 
-    def _set_xml_context(self):
-        doc = self._xml_node.doc
+    def _make_xml_context(self, node):
+        doc = node.doc
         ctx = _CtxCleanupWrapper(doc.xpathNewContext())
-        ctx.setContextNode(self._xml_node)
-        self._xml_ctx = ctx
+        ctx.setContextNode(node)
+        return ctx
+
+    def _set_xml_context(self):
+        self._xml_ctx = self._make_xml_context(self._xml_node)
 
     def _parsexml(self, xml, node):
         if xml:
             doc = libxml2.parseDoc(xml)
             self._xml_root_doc = _DocCleanupWrapper(doc)
             self._xml_node = doc.children
+            self._xml_node.virtinst_is_build = self._is_build
             self._xml_dump_xpath = "."
 
             # This just stores a reference to our root doc wrapper in
@@ -699,41 +734,19 @@ class XMLBuilder(object):
             self._xml_node.virtinst_root_doc = self._xml_root_doc
         else:
             self._xml_node = node
+            self._is_build = (getattr(node, "virtinst_is_build", False) or
+                              self._is_build)
             self._xml_dump_xpath = self._XML_ROOT_XPATH
 
         self._set_xml_context()
 
-    def all_xml_props(self):
-        ret = {}
-        for c in reversed(type.mro(self.__class__)[:-1]):
-            for key, val in c.__dict__.items():
-                if val.__class__ is XMLProperty:
-                    ret[key] = val
-        return ret
-
-    def _do_add_parse_bits(self, xml, node):
+    def _do_add_parse_bits(self, node, ctx):
         # Set all defaults if the properties have one registered
         xmlprops = self.all_xml_props()
-        for prop in xmlprops.values():
-            prop._set_default(self)
 
-        # Default props alter our _propstore. But at this point _propstore
-        # is empty, there's nothing for us to do, so exit early
-        if not self._propstore:
-            return xml
-
-        # Unindent XML
-        indent = 0
-        if xml:
-            for c in xml:
-                if c != " ":
-                    break
-                indent += 1
-            xml = "\n".join([l[indent:] for l in xml.splitlines()])
-
-        # Parse the XML into our internal state. Use the raw
-        # _parsexml so we don't hit Guest parsing into its internal state
-        XMLBuilder._parsexml(self, xml, node)
+        if self.is_build():
+            for prop in xmlprops.values():
+                prop._set_default(self)
 
         # Set up preferred XML ordering
         do_order = self._proporder[:]
@@ -747,32 +760,26 @@ class XMLBuilder(object):
         # Alter the XML
         for key in do_order:
             if key in xmlprops:
-                xmlprops[key].setter(self, self._propstore[key],
-                                     validate=False)
-            else:
-                for obj in util.listify(getattr(self, key)):
-                    if self._xml_root_xpath and not obj._xml_root_xpath:
-                        obj._xml_root_xpath = self._xml_root_xpath
-                    obj._add_parse_bits(xml=None, node=self._xml_node)
+                xmlprops[key]._set_xml(self, self._propstore[key], node)
+                continue
 
-        return _indent(self._do_get_xml_config(), indent)
+            for obj in util.listify(getattr(self, key)):
+                if self._xml_root_xpath and not obj._xml_root_xpath:
+                    obj._xml_root_xpath = self._xml_root_xpath
+                obj._add_parse_bits(node, ctx)
 
-    def _add_parse_bits(self, xml, node=None):
+        return self._get_node_xml(ctx)
+
+    def _add_parse_bits(self, node, ctx):
         """
         Callback that adds the implicitly tracked XML properties to
         the manually generated xml. This should only exist until all
         classes are converted to all parsing all the time
         """
-        if self._is_parse():
-            return xml
-
         origproporder = self._proporder[:]
         origpropstore = self._propstore.copy()
         try:
-            return self._do_add_parse_bits(xml, node)
+            return self._do_add_parse_bits(node, ctx)
         finally:
-            self._xml_root_doc = None
-            self._xml_node = None
-            self._xml_ctx = None
             self._proporder = origproporder
             self._propstore = origpropstore