2015-06-19 2 views
1

Здесь он получает XML-документ и отдельные узлы и вставляет узлы в словарь.Почему эта программа не имеет доступа к дочерним узлам?

//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++; 
     } 
    } 
} 

Позже узлы получают доступ, чтобы сохранить информацию в веб-службе. Однако узлы с дочерними узлами внутри не отображаются таким образом.

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

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

Образец XML документ

<?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> 
+0

Какой парсер XML вы используете? – Ediac

+0

Не могли бы вы попытаться форматировать свой код? Также неясно, какова ваша проблема - что значит «не появляться таким образом»? Я подозреваю, что ничто из этого не работает, потому что вы проигнорировали пространство имен этих элементов. Есть ли причина, по которой вы используете 'XmlDocument', а не LINQ to XML? –

+0

Если я запускаю ваш код без пространства имен на элементе 'Addresses', он работает. Мой XPath - это мусор, хотя и не уверен, что вам нужно сделать для выражения, чтобы получить нужный материал. :) – Chris

ответ

1

Проблема у вас есть с пространствами имен. Если вы укажете пространство имен для каждого из этих элементов, это, похоже, сработает. Я пришел к такому выводу с небольшим количеством поисковых запросов и экспериментов, поэтому мое объяснение не может быть обнаружено, поэтому я советую исследовать проблему дальше, чтобы понять ее правильно.

Этот код будет работать:

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

Причина (я думаю), что в документе XML вы определяете пространство имен по умолчанию для ваших элементов (xmlns="http://24sevenOffice.com/webservices") и в вашем XPath вы не уточнив, что же Пространство имен. В моем коде я создаю диспетчер пространств имен с этим пространством имен и префикс его к двум элементам, которые он теперь считает совпадающими с документами в вашем документе, которые имеют эти пространства имен.

1

Причина, по которой ваш код не работает, вероятно, что вы игнорируете пространство имен тех элементов, которые вы ищете. Есть много вопросов, касающихся того, как это сделать, например, this one.

Это говорит о том, что XmlDocument - это скрипучий старый API, а новый LINQ to XML - это огромное улучшение - я бы предложил вам изучить это.

Я также не уверен, что словарь тянет свой вес за такое небольшое количество элементов. Вы можете просто запросить то, что вам нужно прямо из XML. Например, чтобы получить все поля, как типизированных значений:

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"); 

Вы можете использовать подобную технику, чтобы сопоставить адреса в сильно типизированных Address класс:

var deliveryAddress = order.Elements(ns + "Addresses") 
    .Elements(ns + "Delivery") 
    .Select(e => new Invoice.Address 
    { 
     Street = (string)e.Element(ns + "Street"), 
     // .... 
    }) 
    .Single(); 
Смежные вопросы