How to add an node to an XML Document (via a C# helper that can be called in an expression shape from an orchestration).



First example (uses AppendChild):


<code>
        public static XmlDocument AddExceptionNodeToTMXML(XmlDocument TMXMLDocIn, Exception ex)
        {
            // three import fields in System.Exception are ex.Message, ex.StackTrace, ex.Source
            // then there is an Ex.InnerException

            XmlDocument xmlDocNewTMXML = new XmlDocument();
            xmlDocNewTMXML.LoadXml(TMXMLDocIn.OuterXml);  // make sure we don't update the original TMXMLDocIn

            string errMessage = "";
            string errSource = "";
            string errStackTrace = "";
            string xml;

            if (ex.InnerException == null)
            {
                // if not nested exceptions, do not number them.
                errMessage = ex.Message;
                errStackTrace = ex.StackTrace;
                errSource = ex.Source;
            }
            else
            {
                // loop through all the nested exceptions and concatenate them into single long string variables
                System.Exception innerEx = ex;
                int loopCounter = 0;
                while (innerEx != null)
                {
                    // number the nested exceptions
                    loopCounter++;
                    string separator = "";
                    if (loopCounter &gt; 1)
                        separator = ";";

                    errMessage = errMessage + separator + "n     Ex:" + loopCounter + ") " + innerEx.Message;
                    errStackTrace = errStackTrace + separator + "n     Ex:" + loopCounter + ") " + innerEx.StackTrace;
                    errSource = errSource + separator + "n     Ex:" + loopCounter + ") " + innerEx.Source;
                    innerEx = innerEx.InnerException;

                }

            }

            // Added CDATA clauses below, because the err fields may have
            // ampersand, less-than, greater than, or other problem characters that cause the xmlDoc.Load to  fail. 
            xml =
                    @"&lt;exs:Exceptions xmlns:exs='http://YourSchemaNamespace.Exceptions'&gt;" +
                    "&lt;ex:Exception index='1' id='1' type='' xmlns:ex='http://YourSchemaNamespace.Exception'&gt;" +
                    "  &lt;messageText&gt;&lt;![CDATA[" + errMessage + "]]&gt;&lt;/messageText&gt;" +
                    "  &lt;source&gt;&lt;![CDATA[" + errSource + "]]&gt;&lt;/source&gt;" +
                    "  &lt;stackTrace&gt;&lt;![CDATA[" + errStackTrace + "]]&gt;&lt;/stackTrace&gt;" +
                    "&lt;/ex:Exception&gt;" +
                    "&lt;/exs:Exceptions&gt;";


            XmlDocument exceptionXML = new XmlDocument();
            exceptionXML.LoadXml(xml);


            string strXPathRoot = "/*[local-name()='TMXML' and namespace-uri()='http://YourSchemaNamespace.MainSchema']";
            XmlNode nodeTMXML = xmlDocNewTMXML.SelectSingleNode(strXPathRoot);

            string strExXPathRoot = "/*[local-name()='Exceptions' and namespace-uri()='http://YourSchemaNamespace.Exceptions']";
            XmlNode nodeExceptions = exceptionXML.SelectSingleNode(strExXPathRoot);


            nodeTMXML.AppendChild(xmlDocNewTMXML.ImportNode(nodeExceptions, true));

            return xmlDocNewTMXML;

        }



</code>

Second example (uses CreateElement)


<code>

	// This can be called from a BusinessRule which passes a TypedXmlDocument
	// instead of a normal XmlDocument
	public static void AddItineraryStep(TypedXmlDocument txd, string stepName, string activityPolicy)
        {

                  // can we find the XPath  indicate d?
                  string strXPathRoot = "//*[local-name()='ItinerarySteps']";
                  XmlNode node = LocateXPath(txd, strXPathRoot);
                  if (null == node)
                  {
                      throw new Exception("AddItineraryStep: XPath did not return a valid node, XPath=" +
                          strXPathRoot + "  XML=" + txd.Document.OuterXml);
                  };


                  // determine the root node for the document
                  // if the XPath selects the TXD, it will have no root if it is an XmlDocument
                  // in that case, simply use the document from the TXD
                  XmlDocument root = node.OwnerDocument;
                  if (null == root)
                  {
                        // if the XPath selects the TXD, it may
                        // so fix accordingly
                        root = txd.Document as XmlDocument;
                        if (null == root) return;
                  }


                  // create a new node and add it in
                  string nodeName = "ItineraryStep";
                  XmlElement newNode = root.CreateElement(nodeName);
                  node.AppendChild(newNode);

                  // Not sure why ImportNode not available. Seems like it would be easier
                  //node.AppendChild(txd.Document.ImportNode(nodeItineraryStep, true));

                  //strXPathRoot = "/*[local-name()='Header']/*[local-name()='Itinerary']/*[local-name()='ItineraryStep']";
                  strXPathRoot = "//*[local-name()='ItineraryStep']";
                  node = LocateXPath(txd, strXPathRoot);
                  if (null == node)
                  {
                      throw new Exception("AddItineraryItem: XPath did not return a valid node, XPath=" +
                          strXPathRoot + "  XML=" + txd.Document.OuterXml);
                  };

                  XmlElement newSubNode;

                  nodeName = "name";
                  newSubNode = root.CreateElement(nodeName);
                  newSubNode.InnerText = stepName;
                  newNode.AppendChild(newSubNode);

                  nodeName = "status";
                  newSubNode = root.CreateElement(nodeName);
                  newSubNode.InnerText = "PENDING";
                  newNode.AppendChild(newSubNode);

                  nodeName = "errorType";
                  newSubNode = root.CreateElement(nodeName);
                  // leave value to empty-string (no need to set InnerText)
                  newNode.AppendChild(newSubNode);

                  nodeName = "activityPolicy";
                  newSubNode = root.CreateElement(nodeName);
                  newSubNode.InnerText = activityPolicy;
                  newNode.AppendChild(newSubNode);


        }

        internal static XmlNode LocateXPath(TypedXmlDocument txd, string xPath)
        {
            // does the TXD contain a node?
            XmlNode parent = txd.Document;
            if (null == parent) return null;

            // is there an XPath specified? if not, return the parent
            if ((xPath == null) || (xPath == string.Empty)) return parent;

            // return the first node that the XPath points to
            return parent.SelectSingleNode(xPath, txd.NamespaceManager);
        }

</code>

Tagged with:

Filed under: C#Expression Shapes