简体   繁体   English

C#.NET和解析来自服务器的XML响应

[英]C#.NET and parsing XML response from server

I have several years experience working with JS, Python, and JSON, but just started working with C#.NET and XML within the past week. 我有几年使用JS,Python和JSON的经验,但是在过去一周内才开始使用C#.NET和XML。

I'm having to write a solution for Quickbooks Desktop to consolidate multiple invoice line items into one line item. 我必须为Quickbooks Desktop写一个解决方案,以将多个发票订单项合并为一个订单项。 The examples I have from Intuit are like +10 years old. 我从Intuit获得的示例大约有10年的历史。 It isn't entirely clear to me from SO topics what a modern approach is for my use case: either the answers are +6 years old or it has to do with reading from files--I'm trying to parse a response. 从SO主题对我来说,这还不是很清楚,对于我的用例来说,现代的方法是什么:答案已经使用了6年以上,或者与从文件中读取有关–我正在尝试解析响应。

Here is what the server response looks like (I am temporarily writing it to a file) followed by some questions: 这是服务器响应的样子(我暂时将其写到文件中),后面是一些问题:

<QBXML>
  <QBXMLMsgsRs>
    <InvoiceQueryRs requestID="0" statusCode="0" statusSeverity="Info" statusMessage="Status OK">

      <!-- RECORD 1 -->
      <InvoiceRet>
        <TxnID>3B58B-1540309911</TxnID>
        <EditSequence>1540587328</EditSequence>
        <TxnNumber>27058</TxnNumber>
        <CustomerRef>
          <ListID>800006FF-1540307596</ListID>
          <FullName>Test Co.:Test 1</FullName>
        </CustomerRef>
        <RefNumber>L-9</RefNumber>
        <Subtotal>2212.00</Subtotal>
        <BalanceRemaining>2212.00</BalanceRemaining>
        <IsPaid>false</IsPaid>

        <!-- RECORD 1: INVOICE LINE ITEM 1 -->
        <InvoiceLineRet>
          <TxnLineID>3B58D-1540309911</TxnLineID>
          <ItemRef>
            <ListID>80000002-1443563699</ListID>
            <FullName>Consulting Fees</FullName>
          </ItemRef>
          <Desc>PROJECT: Test 1; TASK: Wrap-up</Desc>
          <Quantity>6</Quantity>
          <Rate>220</Rate>
          <Amount>1320.00</Amount>
        </InvoiceLineRet>

        <!-- RECORD 1: INVOICE LINE ITEM 2 -->
        <InvoiceLineRet>
          <TxnLineID>3B58E-1540309911</TxnLineID>
          <ItemRef>
            <ListID>80000002-1443563699</ListID>
            <FullName>Consulting Fees</FullName>
          </ItemRef>
          <Desc>PROJECT: Test 1; TASK: Kickoff</Desc>
          <Quantity>4</Quantity>
          <Rate>220</Rate>
          <Amount>880.00</Amount>
        </InvoiceLineRet>

        <!-- RECORD 1: INVOICE LINE ITEM 3 -->
        <InvoiceLineRet>
          <TxnLineID>3B58F-1540309911</TxnLineID>
          <ItemRef>
            <ListID>80000025-1538518495</ListID>
            <FullName>Travel:Travel Meals</FullName>
          </ItemRef>
          <Desc>DATE: Oct 23, 2018; PROJECT: Test 1</Desc>
          <Rate>12</Rate>
          <Amount>12.00</Amount>
        </InvoiceLineRet>
      </InvoiceRet>

      <!-- RECORD 2 -->
      <InvoiceRet>
        <TxnID>3B595-1540830324</TxnID>
        <EditSequence>1540830324</EditSequence>
        <TxnNumber>27060</TxnNumber>
        <CustomerRef>
          <ListID>80000700-1540307618</ListID>
          <FullName>Test Co.:Test 2</FullName>
        </CustomerRef>
        <RefNumber>L-11</RefNumber>
        <Subtotal>2760.00</Subtotal>
        <BalanceRemaining>2760.00</BalanceRemaining>

        <!-- RECORD 2: INVOICE LINE ITEM 1 -->
        <InvoiceLineRet>
          <TxnLineID>3B597-1540830324</TxnLineID>
          <ItemRef>
            <ListID>80000002-1443563699</ListID>
            <FullName>Consulting Fees</FullName>
          </ItemRef>
          <Desc>PROJECT: Test 2; TASK: Prebill Task</Desc>
          <Rate>1000</Rate>
          <Amount>1000.00</Amount>
        </InvoiceLineRet>

        <!-- RECORD 2: INVOICE LINE ITEM 2 -->
        <InvoiceLineRet>
          <TxnLineID>3B598-1540830324</TxnLineID>
          <ItemRef>
            <ListID>80000002-1443563699</ListID>
            <FullName>Consulting Fees</FullName>
          </ItemRef>
          <Desc>PROJECT: Test 2; TASK: Present Findings</Desc>
          <Quantity>3</Quantity>
          <Rate>0.00</Rate>
          <Amount>0.00</Amount>
        </InvoiceLineRet>

        <!-- RECORD 2: INVOICE LINE ITEM 3 -->
        <InvoiceLineRet>
          <TxnLineID>3B599-1540830324</TxnLineID>
          <ItemRef>
            <ListID>80000002-1443563699</ListID>
            <FullName>Consulting Fees</FullName>
          </ItemRef>
          <Desc>PROJECT: Test 2; TASK: Research</Desc>
          <Quantity>2</Quantity>
          <Rate>220</Rate>
          <Amount>440.00</Amount>
        </InvoiceLineRet>

        <!-- RECORD 2: INVOICE LINE ITEM 4 -->
        <InvoiceLineRet>
          <TxnLineID>3B59A-1540830324</TxnLineID>
          <ItemRef>
            <ListID>80000002-1443563699</ListID>
            <FullName>Consulting Fees</FullName>
          </ItemRef>
          <Desc>PROJECT: Test 2; TASK: Project Launch</Desc>
          <Quantity>6</Quantity>
          <Rate>220</Rate>
          <Amount>1320.00</Amount>
        </InvoiceLineRet>
      </InvoiceRet>

    </InvoiceQueryRs>
  </QBXMLMsgsRs>
</QBXML>
  1. In general, what is the modern approach to parsing this so that each element can be referred to? 通常,解析该元素以便可以引用每个元素的现代方法是什么?

Something like xml.InvoiceRet[0].TxnId which would be 3B58B-1540309911 . xml.InvoiceRet[0].TxnId类的东西,它将是3B58B-1540309911

  1. How is each record referred to given that the parent node <InvoiceRet> is nondescript? 给定父节点<InvoiceRet>是非描述<InvoiceRet> ,如何引用每个记录? Do you have to iterate through each <InvoiceRet> ? 您是否必须遍历每个<InvoiceRet>

What I have tried from the Intuit documentation: 我从Intuit文档中尝试了什么:

// this is where the query is sent to the QB and response is returned
var responseSet = sessionManager.DoRequests(requestSet);

// take the response and get the first element, I guess?
var response = responseSet.ResponseList.GetAt(0);
var customerRetList = response.Detail as ICustomerRetList;

// print the number of records
// it should be 2, but comes back with nothing
Console.WriteLine(customerRetList.Count);

I put results into a datatable so results are flat. 我将结果放入数据表中,因此结果是平坦的。 I got results from a file. 我从文件中得到结果。 The Load method with work with either a URL or filename. 使用URL或文件名的Load方法。 Replace Load() with Parse() if you have a string. 如果您有字符串,请用Parse()替换Load()。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("TxnID", typeof(string));
            dt.Columns.Add("EditSequence", typeof(string));
            dt.Columns.Add("TxnNumber", typeof(string));
            dt.Columns.Add("CustomerRef_ListID", typeof(string));
            dt.Columns.Add("CustomerRef_FullName", typeof(string));
            dt.Columns.Add("RefNumber", typeof(string));
            dt.Columns.Add("Subtotal", typeof(decimal));
            dt.Columns.Add("BalanceRemaining", typeof(decimal));
            dt.Columns.Add("IsPaid", typeof(Boolean));
            dt.Columns.Add("ItemRef_ListID", typeof(string));
            dt.Columns.Add("ItemRef_FullName", typeof(string));
            dt.Columns.Add("Desc", typeof(string));
            dt.Columns.Add("Quantity", typeof(int));
            dt.Columns.Add("Rate", typeof(decimal));
            dt.Columns.Add("Amount", typeof(decimal));


            XDocument doc = XDocument.Load(FILENAME);

            foreach (XElement invoiceRet in doc.Descendants("InvoiceRet"))
            {
                string txnId = (string)invoiceRet.Element("TxnID");
                string editSequence = (string)invoiceRet.Element("EditSequence");
                string txnNumber = (string)invoiceRet.Element("TxnNumber");
                XElement customerRef = invoiceRet.Element("CustomerRef");
                string custListId = (string)customerRef.Element("ListID");
                string custFullName = (string)customerRef.Element("FullName");
                string refNumber = (string)invoiceRet.Element("RefNumber");
                decimal subtotal = (decimal)invoiceRet.Element("Subtotal");
                decimal balance = (decimal)invoiceRet.Element("BalanceRemaining");
                Boolean? isPaid = (Boolean?)invoiceRet.Element("IsPaid");

                foreach (XElement invoiceLine in invoiceRet.Elements("InvoiceLineRet"))
                {
                    string lineListId = (string)invoiceLine.Descendants("ListID").FirstOrDefault();
                    string lineFullName = (string)invoiceLine.Descendants("FullName").FirstOrDefault();
                    string desc = (string)invoiceLine.Element("Desc");
                    int? quantity = (int?)invoiceLine.Element("Quantity");
                    decimal rate = (decimal)invoiceLine.Element("Rate");
                    decimal amount = (decimal)invoiceLine.Element("Amount");

                    dt.Rows.Add(new object[] {
                        txnId, editSequence, txnNumber, custListId, custFullName,
                        refNumber, subtotal, balance, isPaid, 
                        lineListId, lineFullName, desc, quantity, rate, amount 
                    });


                }
            }
        }
    }
}

It seems like for my use case, Basic Query (LINQ to XML) would be the best option. 在我的用例中, 基本查询(LINQ to XML)似乎是最好的选择。 Decided to parse the response to a string using: 决定使用以下方法解析对字符串的响应:

// Do the request and get the response message set object
var responseSet = sessionManager.DoRequests(requestSet);

// Convert response to string
var responseXml = responseSet.ToXMLString();

// Then the LINQ to XML for the string that I'm still working through
var xmlDoc = XDocument.Parse(responseXml);

// Set the xmlDoc root
var xmlDocRoot = xmlDoc.Root.Element("QBXMLMsgsRs")
                            .Element("InvoiceQueryRs")
                            .Elements("InvoiceRet");


// Iterate through the elements to get values and do some logic
foreach (var invoiceElement in xmlDocRoot)
{
    var editSequence = (string) invoiceElement.Element("EditSequence");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM