     }
     
     public func parseXML(nodes: Container, elem: XMLElement) {
-        if let id = elem.attributes["id"] {
-            self.id = id
-        }
-        
+        if let id = elem.attributes["id"] { self.id = id }
         if let parentDescriptor = elem.attributes["parent-descriptor"] {
             let parentDesc = nodes.resolve(VertexDescriptorNode.self, name: parentDescriptor)!
             self.parentDescriptor = parentDesc
         }
-        
         let attributeSelector = "vertex-attributes > vertex-attribute"
         for (idx, el) in elem.css(attributeSelector).enumerate() {
             if let ref = el.attributes["ref"] {

    }

    public func parseXML(container: Container, elem: XMLElement) {
        if let id = elem.attributes["id"] {
            self.id = id
        }
        if let type = elem.attributes["type"] {
            self.type = type
        }
        let genArgsSelector = "generator-args > generator-arg"
        for (idx, el) in elem.css(genArgsSelector).enumerate() {
            let name = el.attributes["name"]!

    public func parseXML(nodes: Container, elem: XMLElement) {
        // N.B. scale first, then rotate, finally translate
        // - but how can a shear operation be composed into this?
        if let id = elem.attributes["id"] { self.id = id }
        if let scale = elem.attributes["scale"] { self.scale = SpectraSimd.parseFloat3(scale) }
        if let shear = elem.attributes["shear"] { self.shear = SpectraSimd.parseFloat3(shear) }
        if let translation = elem.attributes["translation"] { self.translation = SpectraSimd.parseFloat3(translation) }
        
        if let rotation = elem.attributes["rotation"] {
            self.rotation = SpectraSimd.parseFloat3(rotation)
        } else if let rotationDeg = elem.attributes["rotation-deg"] {
            let rotationDegrees = SpectraSimd.parseFloat3(rotationDeg)
            self.rotation = Float(M_PI / 180.0) * rotationDegrees
        }
    }

