2015-07-21 65 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