static void AddElements(Eagle.parts parts, Dictionary<string, Package> packageMap, 
            Eagle.libraries libs, Eagle.elements elements)
        {
            foreach (var part in parts.part)
            {
                Eagle.element element = new Eagle.element();
                element.name = part.name;
                element.library = part.library;
                var devset =
                    libs.library.Where(l => l.name.Equals(part.library)).                     // find library
                    SelectMany(l => l.devicesets.deviceset).Where(ds => ds.name.Equals(part.deviceset)).    // find deviceset
                    FirstOrDefault();
                var device = devset != null ?
                    devset.devices.device.Where(d => d.name.Equals(part.device)).             // find device
                    FirstOrDefault() : null;
                var tech = device != null ?
                    device.technologies.technology.Select(t => t.name).FirstOrDefault() : null;

                if (devset == null || device == null)
                {
                    Console.WriteLine("ERROR: part {0} does not have device or deviceset information in schema file", part.name); 
                    continue;
                }
                element.package = device.package;

                if (devset.uservalue.ToString().Equals("no"))
                {
                    var value = devset.name + device.name;
                    element.value = value.Replace("*", tech);
                }

                if (packageMap.ContainsKey(part.name))
                {
                    var pkg = packageMap[part.name];
                    // multiple with 10, floor and divide by 10 to align place on a 0.1 mm grid 
                    double pkgx = (pkg.x != null) ? (double)pkg.x : 0.0;
                    double pkgy = (pkg.y != null) ? (double)pkg.y : 0.0;
                    int prot = (pkg.rotation != null) ? (int)pkg.rotation : 0;
                    double x = 0.1 * Math.Floor(10.0 * (pkgx + 
                        ((prot % 2)  == 1 ? pkg.height/2.0 : pkg.width/2.0)));
                    double y = 0.1 * Math.Floor(10.0 * (pkgy + 
                        ((prot % 2)  == 1 ? pkg.width/2.0 : pkg.height/2.0)));
                    double xorg = pkg.originX != null ? (double)pkg.originX : 0.0;
                    double yorg = pkg.originY != null ? (double)pkg.originY : 0.0;
                    switch (prot)
                    {
                        case 0: x -= xorg; y -= yorg; break;
                        case 2: x += xorg; y += yorg; break;
                        case 1: x -= yorg; y -= xorg; break;
                        case 3: x += yorg; y += xorg; break;
                    }

                    double rx = x;
                    double ry = y;

                    if (pkg.RelComponentID != null &&
                        packageMap.ContainsKey(pkg.RelComponentID))
                    // part has a relative placement
                    {
                        var refPkg = packageMap[pkg.RelComponentID];
                        // rotate the contained parts according to refPkg rotation
                        if (refPkg.rotation != null) prot += (int)refPkg.rotation;
                        if (prot > 3) prot = prot % 4;

                        RotateAndTranslate(refPkg, x, y, out rx, out ry);
                    }
                    element.x = rx.ToString();
                    element.y = ry.ToString();
                    string layer = ((pkg.layer == 1) ? "M" : "");
                    string rot = (90 * prot).ToString();
                    element.rot = layer + "R" + rot;
                }
                else
                {
                    Console.WriteLine("WARNING: part {0} not found in layout file", part.name);
                }

                foreach (var sattrib in device.technologies.technology.SelectMany(t => t.attribute))
                {
                    Eagle.attribute dattrib = new Eagle.attribute();
                    dattrib.name = sattrib.name;
                    dattrib.value = sattrib.value;
                    dattrib.layer = ATTRIB_LAYER;
                    dattrib.display = Eagle.attributeDisplay.off;

                    element.attribute.Add(dattrib);
                }


                elements.element.Add(element);
            }
        }
 public static bool LoadFromFile(string fileName, out element obj) {
     System.Exception exception = null;
     return LoadFromFile(fileName, out obj, out exception);
 }
 public static bool Deserialize(string xml, out element obj) {
     System.Exception exception = null;
     return Deserialize(xml, out obj, out exception);
 }
 /// <summary>
 /// Deserializes xml markup from file into an element object
 /// </summary>
 /// <param name="fileName">string xml file to load and deserialize</param>
 /// <param name="obj">Output element object</param>
 /// <param name="exception">output Exception value if deserialize failed</param>
 /// <returns>true if this XmlSerializer can deserialize the object; otherwise, false</returns>
 public static bool LoadFromFile(string fileName, out element obj, out System.Exception exception) {
     exception = null;
     obj = default(element);
     try {
         obj = LoadFromFile(fileName);
         return true;
     }
     catch (System.Exception ex) {
         exception = ex;
         return false;
     }
 }
 /// <summary>
 /// Deserializes workflow markup into an element object
 /// </summary>
 /// <param name="xml">string workflow markup to deserialize</param>
 /// <param name="obj">Output element object</param>
 /// <param name="exception">output Exception value if deserialize failed</param>
 /// <returns>true if this XmlSerializer can deserialize the object; otherwise, false</returns>
 public static bool Deserialize(string xml, out element obj, out System.Exception exception) {
     exception = null;
     obj = default(element);
     try {
         obj = Deserialize(xml);
         return true;
     }
     catch (System.Exception ex) {
         exception = ex;
         return false;
     }
 }