2015-07-21 67 views
0

XML账单通常有一个返回并解析的节点。我们遇到了XML账单有多个节点的问题。由于代码没有设置来处理这个问题,所以客户最终得到了一个不正确的账单。读取多个XML节点而不是一个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; 
} 

于是久违回到它被称为..即时通讯及彼无效arguement 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不具有SelectNodes作为扩展方法。我通过这种方法大量使用这种扩展方法。所以我收到很多错误。

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

我该如何解决我的无效参数,以便我可以使用xmlNodeList而不是xmlNode?有没有办法转换或施放?或者是否有另一个可以使用的xml对象?

因为我现在正在返回多个节点。我知道我需要循环访问customerBill部分。如何在不为每个节点创建新账单的情况下做到这一点?一个xml中的所有节点都需要包含在一个账单中。

+0

这似乎是你想让别人为你做重构工作;你似乎明白你需要做什么,为什么不直接去做呢? –

+0

我是一个非常新的程序员。据我了解我需要做什么,我不确定如何做到这一点。我所做的尽可能多,因为我知道如何。任何帮助或指导将帮助 –

+0

Mayby你应该使用xmlserializer来代替它,它可能会简化你的代码,如果你觉得它适合你。看到我的答案在这里:http://stackoverflow.com/questions/29850559/change-xml-structure-with-linq-and-having-a-foreach-issue/29850793#29850793 – Fjodr

回答

0

从您所提供的代码,这需要考虑到您的重构为XmlNodeList只有一部分是GetServiceAccountUsageAndBillingDetail(),所以你有两个选择:

  1. 更新GetServiceAccountUsageAndBillingDetail()采取的XmlNodeList参数,而不是和方法内聚合值拿出最终ServiceAddressBillDetail OB JECT。
  2. 环路穿过XmlNodeListXmlNode对象和协调不同ServiceAddressBillDetail对象自己。

没有关于什么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对象属性。

+0

谢谢你的帮助。最后一个问题给你。我需要遍历使用“的foreach(VAR saDetailedPageNode在xmlBillParser.GetDetailPageSectionBySA(requestSA,xmlBill的customerBill部分IM)'但即时得到一个错误。有没有更好的办法做到这一点? –

+0

我正在循环通过VAR customerBill =新CustomerBill(); customerBill.IsSurepay = XmlBillParser.GetSurepayFlagFromBill(文件); customerBill.ServiceAddress = XmlBillParser.GetServiceAddress(requestSa,文档); customerBill.monthName = XmlBillParser.GetnillStatementDate(requestSa,xmlBill); customerBill.EqCurlPlanBal = XmlBillParser customerElementCurrentPlanBalance(document); customerBill.EqPymntDue = XmlBillParser.getEqualizerPaymentDue(document); customerBill.Service = GetServiceAccountUsageAndBillingDetail(requestSa,xmlBill,saDetailedPageNode); a然后返回回复 –

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

任何指导或例子,我需要什么将其更改为搜索特定元素 –

+0

如果您选择要用XPath查询的元素,则可以使用与选定元素减去//相似的XPath。 我编辑了答案来添加解决类似问题的代码。 – CooncilWorker