1

Here it gets the XML document and individual nodes, and inserts the nodes into a dictionary.

//create the xml document obj
XmlDocument inputXMLDoc = new XmlDocument();
fileref.isValid = false;
//load the xml document
#region
try
{
    inputXMLDoc.XmlResolver = null;
    inputXMLDoc.Load( strfile );//load the xml file
    string input = inputXMLDoc.OuterXml;//get the string

    Console.WriteLine( "success,loaded XML" );
    logger.Log( "loaded xml:" + strfile );


    fileref.importList = new Dictionary<string, XmlNode>();

    nodeNames = new List<string> { "OrderId", "CustomerId", "CustomerName", "Addresses", "OrderStatus", "DateOrdered", "PaymentTime", "IncludeVAT", "OrderTotalIncVat", "OrderTotalVat", "Currency", "TypeOfSaleId" };

    try
    {
        int i = 0;
        foreach( string name in nodeNames )
        {
            Console.WriteLine( "Adding xml node " + name );

            if( inputXMLDoc.GetElementsByTagName( name ) != null )
            {
                XmlNodeList xlist = inputXMLDoc.GetElementsByTagName( name );

                foreach( XmlNode node in xlist )
                {
                    fileref.importList.Add( name, node );
                    //add individual node within nodelist
                    Console.WriteLine( name );

                }
            } //add specified node from XML doc
            else
            {
                nodeNames.RemoveAt( i );
            }
            i++;
        }
    }
}

Later, the nodes are accessed to save the information to a web service. However, nodes with child nodes within are not showing up this way.

 Invoices.Address address = new Invoices.Address();

 XmlNodeList oNodeList = fileref.importList["Addresses"].SelectNodes("/Delivery/Street");
 foreach (XmlNode xn in oNodeList)
 {
     address.Street = xn.InnerText;
 }

Sample XML document

<?xml version="1.0" encoding="utf-8"?>
<InvoiceOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <OrderId xmlns="http://24sevenOffice.com/webservices">35</OrderId>
  <CustomerId xmlns="http://24sevenOffice.com/webservices">21</CustomerId>
  <CustomerName xmlns="http://24sevenOffice.com/webservices">James Bond</CustomerName>
  <Addresses xmlns="http://24sevenOffice.com/webservices">
    <Delivery>
      <Street>11 Shewell Walk</Street>
      <State />
      <PostalCode>CO1 1WG</PostalCode>
      <PostalArea>Essex</PostalArea>
      <Name />
      <City>Colchester</City>
      <Country>UK</Country>
    </Delivery>
    <Invoice>
      <Street>10 Shewell Walk</Street>
      <State />
      <PostalCode>CO1 1WG</PostalCode>
      <PostalArea>Essex</PostalArea>
      <Name />
      <City>Colchester</City>
      <Country>UK</Country>
    </Invoice>
  </Addresses>
  <OrderStatus xmlns="http://24sevenOffice.com/webservices">Offer</OrderStatus>
  <DateOrdered xmlns="http://24sevenOffice.com/webservices">2015-06-15T14:00:00Z</DateOrdered>
  <PaymentTime xmlns="http://24sevenOffice.com/webservices">14</PaymentTime>
  <IncludeVAT xsi:nil="true" xmlns="http://24sevenOffice.com/webservices" />
  <OrderTotalIncVat xmlns="http://24sevenOffice.com/webservices">480.0000</OrderTotalIncVat>
  <OrderTotalVat xmlns="http://24sevenOffice.com/webservices">80.0000</OrderTotalVat>
  <Currency xmlns="http://24sevenOffice.com/webservices">
    <Symbol>LOCAL</Symbol>
  </Currency>
  <TypeOfSaleId xmlns="http://24sevenOffice.com/webservices">-100</TypeOfSaleId>
  <InvoiceRows xmlns="http://24sevenOffice.com/webservices">
    <InvoiceRow>
      <ProductId>18</ProductId>
      <RowId>4665754</RowId>
      <Price>400.0000</Price>
      <Name>17" Laptop Screen</Name>
      <DiscountRate>0.0000</DiscountRate>
      <Quantity>7.0000</Quantity>
      <Cost>0.0000</Cost>
      <InPrice>0.0000</InPrice>
    </InvoiceRow>
  </InvoiceRows>
</InvoiceOrder>
Chuck Savage
  • 11,775
  • 6
  • 49
  • 69
J.J.
  • 1,128
  • 2
  • 23
  • 62
  • Which XML parser are you using? – Ediac Jun 19 '15 at 16:00
  • Could you try formatting your code? It's also unclear what your issue is - what does ' are not showing up this way' mean? I suspect none of this works because you've ignored the namespace of these elements. Is there any reason you're using `XmlDocument` rather than LINQ to XML? – Charles Mager Jun 19 '15 at 16:01
  • If I run your code without the namespace on the `Addresses` element it works. My XPath is rubbish though so not sure what you need to do to the expression to get the stuff you want. :) – Chris Jun 19 '15 at 16:09

2 Answers2

1

The problem you have is with namespaces. If you specify the namespace for each of those elements then it seems to work. I came to this conclusion with a bit of googling and some experimentation so my explanation might not be spot on so I advise researching the issue further yourself to understand it correctly.

This code will work:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(inputXMLDoc.NameTable);
nsmgr.AddNamespace("ns", "http://24sevenOffice.com/webservices");
var oNodeList = importList["Addresses"].SelectNodes("//ns:Delivery/ns:Street",nsmgr);

The reason is (I think) that in your XML document you are specifying a default namespace for your elements (xmlns="http://24sevenOffice.com/webservices") and in your xpath you are not specifying that same namespace. In my code I create a namespace manager with that namespace in and prefix it to the two elements which it now considers to match the ones in your document that have these namespaces.

Chris
  • 27,210
  • 6
  • 71
  • 92
1

The reason your code doesn't work is likely that you're ignoring the namespace of the elements you're looking for. There are many questions covering how to do that, such as this one.

That said, XmlDocument is a creaky old API and the newer LINQ to XML is a huge improvement - I'd suggest you look into that.

I'm also not sure the dictionary is pulling its weight for such a small number of elements. You can simply query what you need straight from the XML. For example, to get all your fields as typed values:

var doc = XDocument.Parse(strfile);      
var order = doc.Elements("InvoiceOrder").Single();

XNamespace ns = "http://24sevenOffice.com/webservices";

var orderId = (int)order.Element(ns + "OrderId");
var customerId = (int)order.Element(ns + "CustomerId");
var customerName = (string)order.Element(ns + "CustomerName");
var orderStatus = (string)order.Element(ns + "OrderStatus");
var dateOrdered = (DateTime)order.Element(ns + "DateOrdered");
var paymentTime = (int)order.Element(ns + "PaymentTime");
var totalIncVat = (decimal)order.Element(ns + "OrderTotalIncVat");
var totalVat = (decimal)order.Element(ns + "OrderTotalVat");
var currency = (string)order.Elements(ns + "Currency").Elements(ns + "Symbol").SingleOrDefault();
var typeOfSaleId = (int)order.Element(ns + "TypeOfSaleId");

You can use a similar technique to get map your addresses to your strongly typed Address class:

var deliveryAddress = order.Elements(ns + "Addresses")
    .Elements(ns + "Delivery")
    .Select(e => new Invoice.Address
    {
        Street = (string)e.Element(ns + "Street"),
        // ....
    })
    .Single();
Community
  • 1
  • 1
Charles Mager
  • 25,735
  • 2
  • 35
  • 45