/// <summary> /// Traverses Depth-First through the bpmn XML file, collecting and linking all Elements. /// </summary> /// <param name="xNode">The XML node to start with</param> /// <param name="parent">The parent <see cref="BpmnElement"/></param> /// <param name="callingElements">A list to add all <see cref="BpmnElement"/> with a valid 'CalledElement' or 'Process' property.</param> private void RecursiveElements(XElement xNode, BpmnElement parent, ICollection <BpmnElement> callingElements) { var element = new BpmnElement(xNode); if (element.CalledElement != null) { callingElements.Add(element); } else if (element.Process != null) { callingElements.Add(element); } // Only xml nodes with an id can be bpmn elements if (element.Id != null) { try { Elements.Add(element.Id, element); // some tools prefix the ids with a namespace prefix but don't use this namespace to reference it // so if the id contains a prefix, it is mapped with and without it var prefix = xNode.GetPrefixOfNamespace(xNode.Name.Namespace); if (prefix != null) { Elements.Add(prefix + ":" + element.Id, element); } } catch (ArgumentException) { Messages.Add("Error while trying to add second Element with the same id: " + element.Id); } } // Double-link bpmn element to the given parent element if (parent != null) { parent.AddChild(element); } element.Parent = parent; // Call all xml children foreach (var xChild in xNode.Elements()) { var nameSpace = xChild.Name.Namespace; var localName = xChild.Name.LocalName; if (nameSpace.Equals(BpmnNM.Bpmn)) { // Add all bpmn elements to the dictionary RecursiveElements(xChild, element, callingElements); } else if (nameSpace.Equals(BpmnNM.BpmnDi)) { // Parse a diagram as whole if (localName == BpmnDiConstants.BpmnDiagramElement) { var diagram = BuildDiagram(xChild); if (diagram.Plane != null) { Diagrams.Add(diagram); } else { Messages.Add("The plane for diagram + " + diagram.Id + " was not correctly parsed."); } } } else { element.ForeignChildren.Add(xChild); } } }