I am trying get c# to select multiple nodes in XML. I'm not sure how to do this here is the xml code followed by c#:

<PackageTrackingInfo> <TrackingNumber>123456789</TrackingNumber> <PackageDestinationLocation> <City>Seattle</City> <StateProvince>WA</StateProvince> <PostalCode>98107</PostalCode> <CountryCode>US</CountryCode> </PackageDestinationLocation> <PackageDeliveryDate> <ScheduledDeliveryDate>2004-09-15</ScheduledDeliveryDate>

And here is c# code:

public string ProcessXML(string xmlRequest)
        {
            XmlDocument rsp = null;
            Saia.Presentation.Website.SaiaSecure.WebService.Shipment.Response response = new Saia.Presentation.Website.SaiaSecure.WebService.Shipment.Response();
            string testMode = "";

            try
            {
                if (bool.Parse(WebConfigurationManager.AppSettings["Debug"]) == true)
                    File.WriteAllText("c:\\temp\\" + DateTime.Now.ToString("MMddyyy_HHmmss") + ".xml", xmlRequest);
                // Determine Method to Call
                XmlDocument doc = new XmlDocument();
                doc.XmlResolver = null;
                doc.LoadXml(xmlRequest);

                string method = doc.FirstChild.Name;

                if (method.ToLower() == "xml")
                {
                    method = doc.FirstChild.NextSibling.Name;
                }

                if (method == "AmazonTrackingRequest")
                {
                    Saia.Data.General.Shipment prc = new Data.General.Shipment();
                    string pronum = doc.FirstChild.SelectSingleNode("TrackingNumber").InnerText;
                    prc.GetByProNumber(decimal.Parse(pronum));
                    var city = doc.SelectNodes("City");
                var state = doc.SelectNodes("State");
                var postcode = doc.SelectSingleNode("PostalCode");
                ...

                    rsp = new XmlDocument();

                }

            }
            catch (CodeException e)
            {

                Core.Framework.Debug.CodeException(xmlRequest, e);
            }
            catch (Exception e)
            {

                Core.Framework.Debug.Exception(xmlRequest, e);
            }

            return rsp.InnerXml;
        }
    }

Recommended Answers

All 18 Replies

I'm unsure what line 31 is for. Besides what I'm reading on https://social.msdn.microsoft.com/Forums/en-US/3f7c1d0a-2667-4023-908e-731c358bf53c/error-on-xmlresponse?forum=csharpgeneral a google search seems you are posting across the web. No rule against that but it appears something is missing in those posts too.

Then I read "I'm not sure how to do this." Let's read the following FIRST -> https://www.daniweb.com/programming/threads/435023/read-this-before-posting-a-question

The code above doesn't seem to "select" at all. Maybe something lost in translation? When I select words or lines in Word, these are highlighted. But I don't see any GUI above so maybe this is you speaking as selecting in a database? But this needs to be cleared up by you telling more.

The XML file that I posted. I'm trying to get each field to write from that file: Tracking Number, Package Destination Location:City, State, Postal Code, and Scheduled Delivery Date to return nodes in the c# code and I'm not sure if I'm doing that correctly. Does that make sense?

I worry that something is lost in translation. You supplied some XML. Fine but then you write you want to "write from that file." I was under the impression you wanted to read attributes (or values.) For this converstation my lexicon is from https://en.wikipedia.org/wiki/XML

So "write from that file" again sounds like another lost in translation. If only you had written "write to that file" then this almost lines up with your code in which you appear to be trying to write to an XML file.

If you want to write XML files, why not say that? Then folk can offer ideas about the XMLWriter class and so on.

My terminology is not good because I'm not sure what to do. There are two pieces of code I provided: XML and C#. In the if (method == "AmazonTrackingRequest") statement in the C# code, I have a SelectSingleNode for Tracking Number and if you look at the XML code Tracking Number is the first field. I'm not sure how to code the next field in that XML which is City in C# like I did for the Tracking Number field and then so on with the next field State, and then Postal Code... Does that make sense? For example, the code that I have in C# for City:
var city = doc.SelectNodes("City");, I'm not sure if that is correct and that is what I need assistance with.

" I'm not sure how to code the next field in that XML "

Neither am I because in your post you have mixed terms. When you wrote "write from that file." That's where I can't be sure what you want to do. For XML we can write to a file, we read from a file but you wrote something else and now you add more to this by "how to code the next field" before you clear up what you really wanted to do.

I have to think you think and write in another language. Try clearing up what you really wanted to do.

OMG now you are making this more difficult. I'M trying to convert the XML for Amazon web services. I have to write the code in C# to pick up each field that is in the XML.

Try this. Show a hand converted file so folk can see your expected input and expected output.

Then break down the steps from reading your input file, to writing your output file.

You claim I'm making it difficult but you didn't writely clearly what you wanted to do and then, well, we've gone over that.

-> Think about your systems analysis class. That's where we covered how to map out the problem, break it down to steps then head to code to implement those steps.

Expected input and output? I have no idea what you mean here for input. I would guess that would be the code I provided. Do you know anything about Amazon Web Services. The XML code will output those fields for Amazon Web Services.
12345 (TrackingNumber )
Phoenix (City)
AZ (State)
...
That's the expected output.

<PackageTrackingInfo>
    <TrackingNumber>123456789</TrackingNumber>
    <PackageDestinationLocation>
        <City>Seattle</City>
        <StateProvince>WA</StateProvince>
        <PostalCode>98107</PostalCode>
        <CountryCode>US</CountryCode>
    </PackageDestinationLocation>
    <PackageDeliveryDate>
        <ScheduledDeliveryDate>2004-09-15</ScheduledDeliveryDate>

Your XML is malformed. There is no </PackageDeliveryDate> or </PackageTrackingInfo> end tag. I assume it's supposed to be this...

<PackageTrackingInfo>
    <TrackingNumber>123456789</TrackingNumber>
    <PackageDestinationLocation>
        <City>Seattle</City>
        <StateProvince>WA</StateProvince>
        <PostalCode>98107</PostalCode>
        <CountryCode>US</CountryCode>
    </PackageDestinationLocation>
    <PackageDeliveryDate>
        <ScheduledDeliveryDate>2004-09-15</ScheduledDeliveryDate>
    </PackageDeliveryDate>
</PackageTrackingInfo>

You have a line checking to see where there is a child called AmazonTrackingRequest, which is not in the XML, so the code doesn't really follow the XML.

As far as the "expected input", I'll speak for myself, not rproffitt, but I'm looking for the value of xmlRequest in line 1. Is that the same as the posted XML?

Is Saia.Presentation.Website.SaiaSecure.WebService.Shipment.Response a Microsoft C# class? An Amazon C# class? Your own C# class?

Seems to me that your question boils down to "How can I parse XML in string form in C#?

Do you know anything about Amazon Web Services.

No. Do we need to know about Amazon Web Services in order to help you?

I believe that there is no file to show. There is the string parameter on line 1 of your code. How it got into that string is irrelevant to the question if I'm reading the thread correctly. And again, please confirm that the string is the XML to be parsed (assuming that it is my corrected XML, plus perhaps an additional line at the top specifying the XML version?

Your XML is malformed.

Unless of course you only posted part of it to give us the general idea...

I don't think I am confused by your word "select", but I am confused by the selecting of "multiple nodes". What string value is the function supposed to return?

commented: The OP did that in other discussions. Parts of the problem missing. It didn't go well. +12

Hi AssertNull,

Yes that XML is part of what I posted and it does have a </PackageDeliveryDate> end tag.

The value of the xml request is

string xmlreq = "<AmazonTrackingRequest xmlns:xsi=\"www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"AmazonTrackingRequest.xsd\"><Validation><UserID>AMZN</UserID><Password>12345</Password></Validation><APIVersion>4.0</APIVersion><TrackingNumber>123456</TrackingNumber></AmazonTrackingRequest> ";

Saia.Presentation.Website.SaiaSecure.WebService.Shipment.Response is my own C# class

After I corrected the XML (like some of the others), I wrote this piece of brutal overkill :)
I know if I had just passed the XDoc, I could use some of the built-in search functions.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace DW_509677
{
   public class CAmazonTrackingObj
   {
      private const char CHR_DELIM = '^';

      public string strTrackingNumber { get; set; }
      public string strCity { get; set; }
      public string strState { get; set; }
      public string strZip { get; set; }
      public string strCountry { get; set; }
      public string strDeliveryDate { get; set; }

      public CAmazonTrackingObj()
      {
         strTrackingNumber = "";
         strCity = "";
         strState = "";
         strZip = "";
         strCountry = "";
         strDeliveryDate = "";
      }

      public CAmazonTrackingObj(CAmazonTrackingObj copy)
      {
         strTrackingNumber = copy.strTrackingNumber;
         strCity = copy.strCity;
         strState = copy.strState;
         strZip = copy.strZip;
         strCountry = copy.strCountry;
         strDeliveryDate = copy.strDeliveryDate;
      }

      private static Func<IEnumerable<XElement>, string, string> getValFromElement =
         (lst_xe, strTarget) => lst_xe.Where(e => e.Name.LocalName.Equals(strTarget)).FirstOrDefault().Value;

      private static Func<IEnumerable<XElement>, string, IEnumerable<XElement>> getElementsFromElement = (lst_xe, strTarget) =>
         lst_xe.Where(e => e.Name.LocalName.Equals(strTarget)).Elements();

      public CAmazonTrackingObj(XElement xe)
      {
         IEnumerable<XElement> lst_pti = xe.Elements();
         IEnumerable<XElement> lst_pdl = getElementsFromElement(lst_pti, "PackageDestinationLocation");
         IEnumerable<XElement> lst_pdd = getElementsFromElement(lst_pti, "PackageDeliveryDate");

         strTrackingNumber = getValFromElement(lst_pti, "TrackingNumber");
         strCity = getValFromElement(lst_pdl, "City");
         strState = getValFromElement(lst_pdl, "StateProvince");
         strZip = getValFromElement(lst_pdl, "PostalCode");
         strCountry = getValFromElement(lst_pdl, "CountryCode");
         strDeliveryDate = getValFromElement(lst_pdd, "ScheduledDeliveryDate");
      }

      public override string ToString()
      {
         char chrDelim = CHR_DELIM;
         return
            strTrackingNumber + chrDelim +
            strCity + chrDelim +
            strState + chrDelim +
            strZip + chrDelim +
            strCountry + chrDelim +
            strDeliveryDate;
      }

      public override bool Equals(object obj)
      {
         return this.ToString().Equals(((CAmazonTrackingObj)obj).ToString());
      }

      public override int GetHashCode()
      {
         return this.ToString().GetHashCode();
      }
   }

   class Program
   {
      static void Main(string[] args)
      {
         XDocument doc = XDocument.Load("c:/science/data/PackageTrackingInfo.xml");
         CAmazonTrackingObj obj = new CAmazonTrackingObj(doc.Elements("PackageTrackingInfo").First());

         Console.WriteLine(obj.ToString());

         Console.WriteLine(
            "TrackingNo={0}\r\nLocation={1}, {2}\r\nDeliveryDate={3}",
            obj.strTrackingNumber, obj.strCity, obj.strState, obj.strDeliveryDate
            );
      }
   }
}
commented: Hope it helps and "there's no kill like overkill." +12

Yep, that's brutal overkill. And quite possibly beyond the OP's level. The problem as I see it is that the OP did not write his post realizing that we only know what he tells us. The goal of an initial post should be to give as much relevant information and code as is needed to answer the question, and no more. One must design the original post from that point of view. We, the readers, do not know what the OP knows, thus what's "obvious" to the OP is not obvious to us, so it must be MADE obvious. The OP must be able to predict what follow-up questions might be asked and try to circumvent them by sticking them in the original post. Almost inevitably, some clarification will be requested. When that happens, the OP needs to answer those questions succinctly. Otherwise it takes ten posts to figure out what the issue is. By then, people tune out.

What many students do not realize is that one of the best teaching techniques is to require the student to explicitly state the problem and the assumptions and everything that is relevant. "Obvious" questions very often drive them nuts, but in fact, the very act of ANSWERING those questions clarifies the OP's thinking process. Who here hasn't gone to a professor, had them ask questions, gotten frustrated, then in the processof clarifying, figured out the answer without any actual advice from the professor?

Thus, the overall approach should not be exasperation, but simply answering the questions.

To the OP, none of this is intended as criticism. I'm simply "helping" in a way that you may not have anticipated, sort of a "Teach a man to fish rather than give a man a fish" lesson. Programming is a very detail-oriented endeavor. Keep in mind that if you get exasperated with obtuse people asking obvious questions, there is nothing more obtuse than a computer.

I still don't know what you are trying to do and I don't know your experience level. I don't want to write a sample C# program showing how to parse XML to get certain values because for all I know, you already know how to do that and are stuck somewhere else.

Here is what I noticed. You posted malformed XML in the original post that did not contain what the code seemed to be looking for. You later posted different XML that matches the program better. I still don't know what the original XML represents. I also see you selecting NODES (plural) representing the city when as far as I can tell, there is only ONE city node. I see no attempt to convert that list of cities in XML form into a string and I have no idea if that's the goal. Ditto for some of the others. I also do not see an answer to my question of what string the function should return.

Again, none of this is criticism. It simply means that I have no idea how to answer your question not due to any lack of C# ability on my part, but simply because I do not know what your goal is, what your experience level is, and where you are stuck. My advice would be to start a new thread giving the full XML string parameter, the desired return value of the function, updated code, and a clear statement of where you are stuck.

commented: I'm barely getting what they are trying to do. OP needs to re-write, answer questions. +0

Just read my last post. I have the word "succinctly" in there. Ha ha. This is an example of "Do what I say, not what I do"!

commented: I read it. Also I saw what you did there. Here's hoping the OP will engage. +0

OK hopefully this clears up what I'm doing a little bit. I'm trying to output XML. Here is some updated code of what I have. I really hope this makes more sense.

I formatted using XElement which is associated with LINQ i believe. It looks like this and this is not all of the code but some it so you get the idea.

Soap.asmx.cs:

public string ProcessXML(string xmlRequest)
        {
            XDocument rspxml = null;
            Saia.Presentation.Website.SaiaSecure.WebService.Shipment.Response response = new Saia.Presentation.Website.SaiaSecure.WebService.Shipment.Response();
            string testMode = "";

            try
            {
                if (bool.Parse(WebConfigurationManager.AppSettings["Debug"]) == true)
                    File.WriteAllText("c:\\temp\\" + DateTime.Now.ToString("MMddyyy_HHmmss") + ".xml", xmlRequest);
                // Determine Method to Call
                XmlDocument doc = new XmlDocument();
                doc.XmlResolver = null;
                doc.LoadXml(xmlRequest);

                string method = doc.FirstChild.Name;

                if (method.ToLower() == "xml")
                {
                    method = doc.FirstChild.NextSibling.Name;
                }

                if (method == "AmazonTrackingRequest")
                {
                    Saia.Data.General.Shipment prc = new Data.General.Shipment();
                    string pronum = doc.FirstChild.SelectSingleNode("TrackingNumber").InnerText;
                    prc.GetByProNumber(decimal.Parse(pronum));

                    rspxml = XDocument.Load("<?xml version=\"1.0\" encoding=\"UTF-8\"?><AmazonTrackingResponse xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"AmazonTrackingResponse.xsd\">");
                    rspxml.Root.Add(new XElement("APIVersion", "4.0"));
                    rspxml.Root.Add(new XElement("PackageTrackingInfo"));
                    rspxml.Root.Element("PackageTrackingInfo").Add(new XElement("TrackingNumber", prc.ProNumber.ToString()));
                    rspxml.Root.Add(new XElement("PackageDestinationLocation"));
                    rspxml.Root.Element("PackageDestinationLocation").Add(new XElement("City", prc.Consignee.ToString()));
                    rspxml.Root.Element("PackageDestinationLocation").Add(new XElement("StateProvince", prc.Consignee.ToString()));
                    rspxml.Root.Element("PackageDestinationLocation").Add(new XElement("PostalCode", prc.Consignee.ToString()));
                    rspxml.Root.Element("PackageDestinationLocation").Add(new XElement("CountryCode", prc.Consignee.ToString()));
                    rspxml.Root.Add(new XElement("PackageDeliveryDate"));
                    rspxml.Root.Element("PackageDeliveryDate").Add(new XElement("ScheduledDeliveryDate", prc.Consignee.ToString()));
                    rspxml.Root.Element("PackageDeliveryDate").Add(new XElement("ReScheduledDeliveryDate", prc.Consignee.ToString()));
                   .....

                }

            }
            catch (CodeException e)
            {

                Core.Framework.Debug.CodeException(xmlRequest, e);
            }
            catch (Exception e)
            {

                Core.Framework.Debug.Exception(xmlRequest, e);
            }

            return rspxml.ToString();
        }

The problem I'm having now is when I debug by stepping into the code it blows up with an 'object is not set to instance of an object' error in the class file on this line:

string response = shipment.ProcessXML(xmlreq);

Class1.cs:

class Class1
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                string flg = string.Empty;
                while (flg != "q")
                {

                    System.Text.StringBuilder request = new System.Text.StringBuilder();
                    saia.shipment.Shipment shipment = new saia.shipment.Shipment();
                    shipment.Timeout = 120000;
                    request.Append("<GetByProNumber>");
                    request.Append("<UserID>chrltl</UserID>");
                    request.Append("<Password>chrltl14800</Password>");
                    request.Append("<TestMode>N</TestMode>");
                    request.Append("<ProNumber>983579110</ProNumber>");
                    request.Append("</GetByProNumber>");

                    string xmlreq = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><AmazonTrackingRequest xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"AmazonTrackingRequest.xsd\"><Validation><UserID>AMZN</UserID><Password>12345</Password></Validation><APIVersion>4.0</APIVersion><TrackingNumber>10143826470</TrackingNumber></AmazonTrackingRequest>";

                    string response = shipment.ProcessXML(xmlreq);
                    System.Xml.XmlDocument xmlResponse = new System.Xml.XmlDocument();
                    xmlResponse.LoadXml(response);

                    // Note: These examples use SelectSingleNode() which accepts a string 
                    // containing a XPath expression. This is a common way to retrieve a node 
                    // from a small XML Document. 

                    if (xmlResponse.SelectSingleNode("/Response/Code").InnerText != "")
                    {
                        // Add error handling code in case Saia responds 
                        // with an Error Code

                        System.Console.WriteLine(xmlResponse.SelectSingleNode("/Response/Code").InnerText);
                        System.Console.WriteLine(xmlResponse.SelectSingleNode("/Response/Element").InnerText);
                        System.Console.WriteLine(xmlResponse.SelectSingleNode("/Response/Fault").InnerText);
                        System.Console.WriteLine(xmlResponse.SelectSingleNode("/Response/Message").InnerText);
                    }
                    else
                    {
                        //System.Console.WriteLine(xmlResponse.SelectSingleNode("/Response/CurrentStatus").InnerText);
                        System.Console.WriteLine(xmlResponse.SelectSingleNode("/Response/Consignee/Name").InnerText);
                        System.Console.WriteLine(xmlResponse.SelectSingleNode("/Response/Consignee/AccountNumber").InnerText);
                        System.Console.WriteLine(xmlResponse.SelectSingleNode("/Response/Consignee/Address1").InnerText);
                        .....
                    }
                    shipment.Dispose();
                    request = null;
                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
                Console.ReadLine();
            }
        }
    }

It seems like it's something wrong with getting into the ProcessXML method but I'm not sure what it could be.

I sincerely hope this makes sense. Again I'm trying to build out the “rspxml” document to generate the output xml.

I still need assistance from someone. I've provided the code and broke down what I need help with. Please someone help.

You're building a string called "request", but I don't see where you're using it.
Also, could you just build that request using the class from the WebService?

...like this:

class Program
   {
      static void Main(string[] args)
      {
         Shipment shipment = new Shipment();

         GetByProNumber req = new GetByProNumber
         {
            Password = "asdf",
            TestMode = "false",
            UserID = "asdf",
            ProNumber = 11
         };

         shipment.GetByProNumber(req);
      }
   }

Am I correct to assume that the ProcessXML function is a member function of the saia.shipment.Shipment class? That's how you are calling it. If not, there's your error.

Change your function to something like this...

public string ProcessXML(string xmlRequest)
{
    Console.WriteLine("Hello World");
    return xmlRequest;
}

Compile it. If it compiles, attempt to run it. See if you get a "Hello World" printout. It looks to me like the error has nothing to do with that function. You need to make sure that ProcessXML is in the saia.shipment.Shipment class. The error you mention makes it appear that it is NOT in that class. The shipment variable IS in that class.

I'll reiterate my advice to start a new thread at this point. Most people aren't going to see and read through this thread, which is probably why it took four days for someone to answer.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.