Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

c# - Add array node to existing xml doc

Posted on 2011-10-20
3
Medium Priority
?
566 Views
Last Modified: 2012-05-12
Hello experts,

I have the following XML:

<?xml version="1.0" encoding="utf-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Body>
    <order xmlns="http://orders.x.x.com">
      <updateOrderRequest xmlns="">
        <orderId>55</orderId>
        <contactName>John Anderson</contactName>
        <unit>1</unit>
        <primaryCustomer>
          <suffix>Mr</suffix>
          <title />
          <firstName>John</firstName>
          <lastName>Anderson</lastName>
          <middleName>J</middleName>
          <CustomerId>5</CustomerId>
          <phoneDetails>
            <phoneId>9999</phoneId>
            <CustomerId>5</CustomerId>
            <primary>true</primary>
            <deviceType>Cell</deviceType>
            <extension></extension>
            <number>5555551234</number>
          </phoneDetails>
          <addressDetails>
            <addressId>1176</addressId>
            <guestLocatorId>5</guestLocatorId>
            <primary>true</primary>
            <addressLine1>1 main st</addressLine1>
            <city>Atlanta</city>
            <country>USA</country>
            <postalCode>55555</postalCode>
            <state>GA</state>
          </addressDetails>
          <doNotMailIndicator>false</doNotMailIndicator>
          <doNotPhoneIndicator>false</doNotPhoneIndicator>
          <active>true</active>
        </primaryCustomer>
        <salesChannelId>2</salesChannelId>        
        <salesChannel>online</salesChannel>
        <authumber>21</authNumber>
      </updateOrderRequest>
    </order>
  </Body>
</Envelope>

And I have the following in memory datatable that I will be reading from to update and hopfully add to the existing xmldoc:
DataTable:
xpath, value, action

/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails'][1]/*[local-name(.)='phoneId'][1] , 9999, update
/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails'][1]/*[local-name(.)='CustomerId'][1] , 5, update
/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails'][1]/*[local-name(.)='primary'][1] , true, update
/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails'][1]/*[local-name(.)='deviceType'][1] , Cell, update
/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails'][1]/*[local-name(.)='number'][1] , 5555551234, update
/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails'][2]/*[local-name(.)='phoneId'][1] , 1000, add
/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails'][2]/*[local-name(.)='CustomerId'][1] , 5, add
/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails'][2]/*[local-name(.)='primary'][1] , false, add
/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails'][2]/*[local-name(.)='deviceType'][1] , Cell, add
/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails'][2]/*[local-name(.)='number'][1] , 5557957600, add
/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails'][2]/*[local-name(.)='extension'][1] , 115, add

I know how I can update the InnerText of each node with the xpath value pair.

Question is:
What is the recommended way to add the 2nd phoneDetails array node to my existing xmldoc?  
I have been toying with the xmlnode clone and insertAfter methods but haven't had much luck.

Expected output would be:

<?xml version="1.0" encoding="utf-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Body>
    <order xmlns="http://orders.x.x.com">
      <updateOrderRequest xmlns="">
        <orderId>55</orderId>
        <contactName>John Anderson</contactName>
        <unit>1</unit>
        <primaryCustomer>
          <suffix>Mr</suffix>
          <title />
          <firstName>John</firstName>
          <lastName>Anderson</lastName>
          <middleName>J</middleName>
          <CustomerId>5</CustomerId>
          <phoneDetails>
            <phoneId>9999</phoneId>
            <CustomerId>5</CustomerId>
            <primary>true</primary>
            <deviceType>Cell</deviceType>            
            <number>5555551234</number>
            <extension />
          </phoneDetails>
          <phoneDetails>
            <phoneId>1000</phoneId>
            <CustomerId>5</CustomerId>
            <primary>false</primary>
            <deviceType>Office</deviceType>
            <number>5557957600</number>
            <extension>115</extension>
          </phoneDetails>
          <addressDetails>
            <addressId>1176</addressId>
            <guestLocatorId>5</guestLocatorId>
            <primary>true</primary>
            <addressLine1>1 main st</addressLine1>
            <city>Atlanta</city>
            <country>USA</country>
            <postalCode>55555</postalCode>
            <state>GA</state>
          </addressDetails>
          <doNotMailIndicator>false</doNotMailIndicator>
          <doNotPhoneIndicator>false</doNotPhoneIndicator>
          <active>true</active>
        </primaryCustomer>
        <salesChannelId>2</salesChannelId>        
        <salesChannel>online</salesChannel>
        <authorizationNumber>21</authorizationNumber>
      </updateOrderRequest>
    </order>
  </Body>
</Envelope>





0
Comment
Question by:j420exe1
  • 2
3 Comments
 
LVL 75

Accepted Solution

by:
käµfm³d   👽 earned 2000 total points
ID: 37002829
I'm not entirely certain of how are storing in memory your "in memory datatable", but if you have it in (or can get it into) an XmlNode, then you should be able to do something like this:

using System.Xml;

namespace _27407277
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument xdoc = new XmlDocument();

            xdoc.Load("input.xml");
            XmlNode phoneNode = xdoc.SelectSingleNode("//phoneDetails[last()]");
            XmlNode newNode = null;  // Assume it is valid here

            phoneNode.InsertAfter(newNode, phoneNode);
        }
    }
}

Open in new window

0
 

Author Comment

by:j420exe1
ID: 37003536
This is what I have so far.

So what I am trying to do is add another phoneDetails array node with it's children to the existing xmldoc.  How can I copy the first occurance of the phoneDetails array and add it to the xmldoc?  


...
XmlNode startNode;
XmlNode parentNode;
m_XmlDoc.Load(m_XmlFileName);
//hardcoded only for this example
string singleNode = "/*[local-name(.)='Envelope'][1]/*[local-name(.)='Body'][1]/*[local-name(.)='order'][1]/*[local-name(.)='updateOrderRequest'][1]/*[local-name(.)='primaryCustomer'][1]/*[local-name(.)='phoneDetails']";
startNode = m_XmlDoc.SelectSingleNode(singleNode);
//get parent node so i know where to add the new child array to
parentNode = startNode.ParentNode;

foreach (DataRow row in myDT.Rows)
{
    object[] array = row.ItemArray;

    string strAction = array[2].ToString();
    if (strAction == "add")
    {
        //addnode
        XmlNode addedNode;
        //add node to xmldoc then populate
        
        XmlNode childNode;
        childNode = m_XmlDoc.SelectSingleNode(array[0].ToString());

        //how can I clone or copy the the first instance of the phoneDetails array node???
        
        
        // Attach the new node 
        parentNode.AppendChild(addedNode);
        // Save the new document
        m_XmlDoc.Save(strNew);

        
    }
    else
    {
        //update
        XmlNode updateNode;
        //get node with xpath
        updateNode = m_XmlDoc.SelectSingleNode(array[0].ToString());
        //update node inner text with value
        updateNode.InnerText = array[1].ToString();

    }

    m_XmlDoc.Save(strNew);
...

Open in new window

0
 

Author Comment

by:j420exe1
ID: 37003589
                   XmlNode phoneNode = m_XmlDoc.SelectSingleNode("//phoneDetails[last()]");
                    XmlNode newNode = phoneNode.CloneNode(true);  // Assume it is valid here

                    parentNode.InsertAfter(newNode, phoneNode);

Changed the phoneNode to the parent Node and it worked.  Thanks.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Najam
Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
this video summaries big data hadoop online training demo (http://onlineitguru.com/big-data-hadoop-online-training-placement.html) , and covers basics in big data hadoop .
Screencast - Getting to Know the Pipeline
Suggested Courses

564 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question