读取多个xml节点而不是一个

时间:2015-07-21 18:29:42

标签: c# xml c#-4.0 xml-parsing

XML账单通常有一个返回和解析的Node。我们遇到过一个XML账单有多个节点的问题。由于代码未设置为处理该代码,因此客户最终收到了错误的账单。

这是我通过账单清单的代码。如果它返回一个节点,那么它将解析来自xml的信息。

    var response = new List<CustomerBill>();
    try
    {
        foreach (GetBillForCAResponse eBillResponse in eBillResponseList)
        {
            var statementDetailsResponse =   GetStatementDetails(
                new GetStatementDetailsRequest
                {
                   BatchId = eBillResponse.BatchId,
                   CustomerAccountId =    eBillResponse.CA.ToString("000000000"),
                   StatementId =   eBillResponse.CAS_NUM.ToString("0000")
                });

           string xmlBill = statementDetailsResponse.StatementAsXML.ToString();
           var document = new XmlDocument();
           document.LoadXml(xmlBill);

           var saDetailedPageNode = XmlBillParser.GetDetailPageSectionBySa(requestSa, xmlBill);
           if (saDetailedPageNode == null) continue;

           var customerBill = new CustomerBill();
           customerBill.IsSurepay = XmlBillParser.GetSurepayFlagFromBill(document);
           customerBill.ServiceAddress = XmlBillParser.GetServiceAddress(requestSa, document);
           customerBill.monthName = XmlBillParser.GetnillStatementDate(requestSa, xmlBill);
           customerBill.EqCurlPlanBal = XmlBillParser.getEqualizerCurrentPlanBalance(document);
           customerBill.EqPymntDue = XmlBillParser.getEqualizerPaymentDue(document);

           customerBill.Service = GetServiceAccountUsageAndBillingDetail(requestSa, xmlBill, saDetailedPageNode);
           response.Add(customerBill);
        }
    }
    catch (Exception ex)
    {
        trace.Write(new InvalidOperationException(requestSa, ex));
    }
    return response;
}

以下是检查XML中是否存在节点的方法。我已经更改了代码,以便返回所有节点。我不得不将类型xmlNode更改为xmlNodeList,因为它现在返回一组节点。 ****这是什么导致我的代码在其他地方的所有问题。***

public static xmlNode GetDetailPageSectionBySa(string sa, string statementXml)
{
    XmlDocument document = new XmlDocument();
    document.LoadXml(statementXml);
    string requestSa = sa.PadLeft(9, '0');
    string xpath = String.Format("//Para[IRBILGP_SA_SAA_ID_PRINT.SERVICE.ACCOUNT.STATMENT='{0}S{1}']/..", requestSa.Substring(0, 4), requestSa.Substring(4));
    return document.SelectNodes(xpath);
    //var nodes = document.SelectNodes(xpath);
   // if(nodes.Count > 0) return nodes[nodes.Count - 1];
    //if(!SaExistInBill(requestSa, statementXml)) return null;
    //var node = GetDetailPageSectionByBillPrisminfoIndex(sa, statementXml);
    //if (node != null) return node;
    //return null;
}

所以回到它被称为的地方..我在这里得到一个无效的争论 customerBill.Service = GetServiceAccountUsageAndBillingDetail(requestSA, xmlBill, saDetailedPageNode);,因为参数saDetailedPageNode现在是xmlNodeList时,预计类型为xmlNode。如果我转到我在此代码末尾添加的方法private static ServiceAddressBillDetail GetServiceAccountUsageAndBillingDetail(string requestSA, string xmlBill, XmlNode detailPageNode),您可以看到。如果我将参数XmlNode detailPageNode更改为XmlNodeList detailPageNode,我必须修复上面的无效争议,我认为detailPageNode.SelectNodes无效,因为xmlNodeList没有{{1}作为扩展方法。我通过这种方法大量使用这种扩展方法。所以我遇到了很多错误。

SelectNodes

如何修复无效参数,以便我可以使用xmlNodeList而不是xmlNode?有没有办法转换或演员?或者我可以使用另一个xml对象吗?

因为我现在正在返回多个节点。我知道我需要遍历 var saDetailedPageNode = XmlBillParser.GetDetailPageSectionBySa(requestSa, xmlBill); if (saDetailedPageNode == null) continue; var customerBill = new CustomerBill(); customerBill.IsSurepay = XmlBillParser.GetSurepayFlagFromBill(document); customerBill.ServiceAddress = XmlBillParser.GetServiceAddress(requestSa, document); customerBill.monthName = XmlBillParser.GetnillStatementDate(requestSa, xmlBill); customerBill.EqCurlPlanBal = XmlBillParser.getEqualizerCurrentPlanBalance(document); customerBill.EqPymntDue = XmlBillParser.getEqualizerPaymentDue(document); customerBill.Service = GetServiceAccountUsageAndBillingDetail(requestSa, xmlBill, saDetailedPageNode); response.Add(customerBill); } } catch (Exception ex) { trace.Write(new InvalidOperationException(requestSa, ex)); } return response; } private static ServiceAddressBillDetail GetServiceAccountUsageAndBillingDetail(string requestSA, string xmlBill, XmlNode detailPageNode) { var saBillDetail = new ServiceAddressBillDetail(); saBillDetail.UsageServiceName = requestSA; var meterReadEndXMLNodes = detailPageNode.SelectNodes("Usage_kWh_b"); if (meterReadEndXMLNodes.Count == 0) { meterReadEndXMLNodes = detailPageNode.SelectNodes("Usage_kWh_a"); } if (meterReadEndXMLNodes.Count == 0) { meterReadEndXMLNodes = detailPageNode.SelectNodes("APSElec_kWh_b"); } if (meterReadEndXMLNodes.Count == 0) { meterReadEndXMLNodes = detailPageNode.SelectNodes("APSElec_kWh_a"); } var demandXMLNodes = detailPageNode.SelectNodes("Usage_kW_Total_Bold"); 部分。如果不为每个节点创建新帐单,我该怎么做?一个xml中的所有节点都需要包含在一个帐单中。

2 个答案:

答案 0 :(得分:0)

很难看到发生了什么,但这可能是问题;

string xpath = String.Format("//Para..

“//”将搜索整个文档,但您可能希望搜索后代元素。

这是一些处理类似问题的代码;

XmlNodeList staffNodes = resultXML.SelectNodes("//staff");
List<TempStaff> tempStaffs = staffNodes
    .Cast<XmlNode>()
    .Select(
        i =>
            new TempStaff()
            {
                StaffId = i.SelectSingleNode("id").InnerText,
                Forename = i.SelectSingleNode("forename").InnerText,
                Surname = i.SelectSingleNode("surname").InnerText,
            }
    ).ToList();

我的XML看起来像

<staff><forename>asdf</forename><surname>ddsf</surname><id>123</id>... </staff>
<staff><forename>asdfas</forename><surname>asffdf</surname><id>456</id>...</staff>

答案 1 :(得分:0)

根据您提供的代码,XmlNodeList的重构需要考虑的唯一部分是GetServiceAccountUsageAndBillingDetail(),因此您有两种选择:

  1. 更新GetServiceAccountUsageAndBillingDetail()以获取XmlNodeList参数,并汇总该方法中的值以提供最终的ServiceAddressBillDetail对象。
  2. 循环浏览XmlNode中的XmlNodeList个对象,并自行协调不同的ServiceAddressBillDetail个对象。
  3. 如果没有ServiceAddressBillDetail的详细信息,我只能猜测哪个更好,但我建议使用第一个选项。

    private static ServiceAddressBillDetail GetServiceAccountUsageAndBillingDetail(
        string requestSA, 
        string xmlBill, 
        XmlNodeList detailPageNodes)
    {
       var saBillDetail = new ServiceAddressBillDetail();
       saBillDetail.UsageServiceName = requestSA;
    
        foreach(XmlNode detailPageNode in detailPageNodes)
        {
            var meterReadEndXMLNodes = detailPageNode.SelectNodes("Usage_kWh_b"); 
    
            if (meterReadEndXMLNodes.Count == 0)
            {
                meterReadEndXMLNodes = detailPageNode.SelectNodes("Usage_kWh_a");
            }
            if (meterReadEndXMLNodes.Count == 0)
            {
                meterReadEndXMLNodes = detailPageNode.SelectNodes("APSElec_kWh_b");
            }
            if (meterReadEndXMLNodes.Count == 0)
            {
                meterReadEndXMLNodes = detailPageNode.SelectNodes("APSElec_kWh_a");
            }
    
            var demandXMLNodes = detailPageNode.SelectNodes("Usage_kW_Total_Bold");
            //Whatever comes next
        }
    }
    

    假设ServiceAddressBillDetail具有“使用”属性,您只需将每个detailPageNode中的相应值添加到saBillDetail对象。