为什么这个程序不访问子节点?

Why is this program not accessing child nodes?

此处它获取 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>

您遇到的问题与命名空间有关。如果您为每个元素指定名称空间,那么它似乎可以工作。我通过一些谷歌搜索和一些实验得出了这个结论,所以我的解释可能不是很准确,所以我建议你自己进一步研究这个问题以正确理解它。

此代码有效:

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 中,您没有指定相同的名称空间。在我的代码中,我创建了一个带有该命名空间的命名空间管理器,并将其添加到它现在认为与文档中具有这些命名空间的元素相匹配的两个元素之前。

您的代码不起作用的原因可能是您忽略了要查找的元素的名称空间。有很多关于如何做到这一点的问题,例如 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 class:

var deliveryAddress = order.Elements(ns + "Addresses")
    .Elements(ns + "Delivery")
    .Select(e => new Invoice.Address
    {
        Street = (string)e.Element(ns + "Street"),
        // ....
    })
    .Single();