简体   繁体   English

您可以帮我解析带有PHP的XML吗?

[英]Can you help me parse this XML w/ PHP?

I'm trying to write a payment and Xero integration for our PSA software. 我正在尝试为我们的PSA软件编写付款和Xero集成。 The billing part has gone pretty well thanks to help around here. 感谢这里的帮助,结算部分进展顺利。 Now the fun part comes: Parsing the Invoice Data from the API of the PSA to usable data that I can feed into Xero... 现在有趣的部分来了:将PSA的API中的发票数据解析为可用的数据,我可以将这些数据输入Xero ...

Here is the XML as it comes from the API: 这是来自API的XML:

<invoice_batch_generic xmlns="http://tempuri.org/invoice_batch_generic.xsd">
    <invoice_batch>
        <batch_id>171</batch_id>
        <create_date>2017-07-11T14:23:39.133-04:00</create_date>
        <create_by_id>29682885</create_by_id>
        <batch_data />
    </invoice_batch>
    <taxregioncategory>
        <tax_category_name />
        <total_tax_rate_per_category_and_region>0.0000000</total_tax_rate_per_category_and_region>
        <total_tax_amount>0.00000</total_tax_amount>
    </taxregioncategory>
    <account>
        <account_id>232</account_id>
        <parent_name />
        <creator_name>Dominic</creator_name>
        <narrative_creator_name>Dominic</narrative_creator_name>
        <territory_name />
        <cust_id />
        <cust_name>Metro </cust_name>
        <taxable>No</taxable>
        <addr1>123 Anywhere Ln</addr1>
        <addr2 />
        <city>Denver</city>
        <account_region>CO</account_region>
        <country>United States</country>
        <postal_code>80203</postal_code>
        <phone>1234567890</phone>
        <fax />
        <attention />
        <billing_addr1>132 anywhere ln</billing_addr1>
        <billing_addr2 />
        <billing_city>Denver</billing_city>
        <billing_region>CO</billing_region>
        <billing_country>United States</billing_country>
        <billing_postal_code>80203</billing_postal_code>
        <billing_attention />
        <tax_id />
        <tax_group_name />
        <parent_id />
        <payment_term_name>NET 15</payment_term_name>
        <account_invoice_email_recipient></account_invoice_email_recipient>
        <invoice>
            <invoice_id>471</invoice_id>
            <account_id>232</account_id>
            <owner_name>Dominic</owner_name>
            <narrative_owner_name>Dominic</narrative_owner_name>
            <invoice_date>2017-07-11T00:00:00-04:00</invoice_date>
            <entry_time_stamp>2017-07-11T14:23:39-04:00</entry_time_stamp>
            <invoice_number>2374</invoice_number>
            <comments />
            <invoice_total>1087.0800</invoice_total>
            <total_tax_value>0.0000</total_tax_value>
            <tax_description />
            <tax_group />
            <date_range_from>2017-08-01T00:00:00-04:00</date_range_from>
            <date_range_to>2017-08-30T00:00:00-04:00</date_range_to>
            <purchase_order_number />
            <payment_term_name>NET 15</payment_term_name>
            <batch_id>171</batch_id>
            <invoice_transferred_flag>No</invoice_transferred_flag>
            <payment_due_date>2017-07-26T00:00:00-04:00</payment_due_date>
            <taxes />
            <invoice_item>
                <invoice_item_id>1</invoice_item_id>
                <invoice_id>471</invoice_id>
                <item_name>SOME STUFF</item_name>
                <item_id>9234</item_id>
                <item_date>2017-08-01T00:00:00-04:00</item_date>
                <adjusted_item_id />
                <type_of_transaction>Recurring Service</type_of_transaction>
                <allocation_code_name>Managed Services</allocation_code_name>
                <allocation_code_external_number />
                <allocation_code_non_billable>No</allocation_code_non_billable>
                <allocation_code_taxable>No</allocation_code_taxable>
                <task_or_ticket_number />
                <task_or_ticket_title>Recurring Service</task_or_ticket_title>
                <ticket_contact />
                <narrative_ticket_contact />
                <adjustment_reason />
                <resource_name> Dominic</resource_name>
                <narrative_resource_name>Dominic </narrative_resource_name>
                <resource_payroll_identifier />
                <role_name />
                <department>Operations</department>
                <project_name />
                <project_lead />
                <narrative_project_lead />
                <external_project_number />
                <internal_project_number />
                <gl_code_desc />
                <gl_code_name />
                <contract_name>Metro 2017</contract_name>
                <external_contract_number />
                <worked_hours>0.0000</worked_hours>
                <non_billable_hours>0.0000</non_billable_hours>
                <billable_hours>0.0000</billable_hours>
                <hourly_billing_rate>21.4800</hourly_billing_rate>
                <extended_price>859.2000</extended_price>
                <time_entry_summary_notes />
                <quantity>40.0000</quantity>
                <expense_type />
                <installed_product_name />
                <subscription_name />
                <subscription_desc />
                <subscription_cost>0.00</subscription_cost>
                <milestone_title />
                <milestone_description />
                <milestone_amount>0.0000</milestone_amount>
                <service_or_bundle_id>63</service_or_bundle_id>
                <service_name>STUFF</service_name>
                <service_invoice_description>STUFF</service_invoice_description>
                <service_units>40</service_units>
                <service_unit_price>21.4800</service_unit_price>
                <service_extended_price>859.2000</service_extended_price>
                <service_period_start_date>2017-08-01T00:00:00-04:00</service_period_start_date>
                <service_period_end_date>2017-08-31T00:00:00-04:00</service_period_end_date>
                <setup_fee>0.0000</setup_fee>
                <billing_approved_by>, Dominic</billing_approved_by>
                <narrative_billing_approved_by>Dominic </narrative_billing_approved_by>
                <approved_date>2017-07-11T11:03:25.957-04:00</approved_date>
                <posted_date>2017-07-10T20:00:00-04:00</posted_date>
                <non_overage_retainer_line_item_tax>0.0000</non_overage_retainer_line_item_tax>
                <gross_amount>859.2000</gross_amount>
                <contract_type>7</contract_type>
                <department_number />
                <effective_hourly_billing_rate>21.4800</effective_hourly_billing_rate>
                <external_product_id />
                <cost_description />
                <project_phase />
                <our_cost>310.0000</our_cost>
                <expense_description />
                <line_item_id>1</line_item_id>
                <tax_region_and_category_id>0</tax_region_and_category_id>
                <tax_region_name />
                <tax_category_name />
                <total_tax_rate_per_region_and_category>0.0000000</total_tax_rate_per_region_and_category>
                <total_tax_amount>0.00000</total_tax_amount>
                <allocation_code_id>29682901</allocation_code_id>
                <serial_number />
                <contract_period_type>m</contract_period_type>
                <service_period_type>m</service_period_type>
                <account_manager_when_posted>, Dominic</account_manager_when_posted>
            </invoice_item>
            <invoice_item>
                <invoice_item_id>2</invoice_item_id>
                <invoice_id>471</invoice_id>
                <item_name>SEServer [Aug 01, 2017 - Aug 31, 2017]</item_name>
                <item_id>9235</item_id>
                <item_date>2017-08-01T00:00:00-04:00</item_date>
                <adjusted_item_id />
                <type_of_transaction>Recurring Service</type_of_transaction>
                <allocation_code_name>Managed Services</allocation_code_name>
                <allocation_code_external_number />
                <allocation_code_non_billable>No</allocation_code_non_billable>
                <allocation_code_taxable>No</allocation_code_taxable>
                <task_or_ticket_number />
                <task_or_ticket_title>Recurring Service</task_or_ticket_title>
                <ticket_contact />
                <narrative_ticket_contact />
                <adjustment_reason />
                <resource_name>, Dominic</resource_name>
                <narrative_resource_name>Dominic </narrative_resource_name>
                <resource_payroll_identifier />
                <role_name />
                <department>Operations</department>
                <project_name />
                <project_lead />
                <narrative_project_lead />
                <external_project_number />
                <internal_project_number />
                <gl_code_desc />
                <gl_code_name />
                <contract_name>Metro  2017</contract_name>
                <external_contract_number />
                <worked_hours>0.0000</worked_hours>
                <non_billable_hours>0.0000</non_billable_hours>
                <billable_hours>0.0000</billable_hours>
                <hourly_billing_rate>110.4800</hourly_billing_rate>
                <extended_price>220.9600</extended_price>
                <time_entry_summary_notes />
                <quantity>2.0000</quantity>
                <expense_type />
                <installed_product_name />
                <subscription_name />
                <subscription_desc />
                <subscription_cost>0.00</subscription_cost>
                <milestone_title />
                <milestone_description />
                <milestone_amount>0.0000</milestone_amount>
                <service_or_bundle_id>62</service_or_bundle_id>
                <service_name>SECURE MANAGED SERVICES: Server</service_name>
                <service_invoice_description>Secure Managed Services Per Server</service_invoice_description>
                <service_units>2</service_units>
                <service_unit_price>110.4800</service_unit_price>
                <service_extended_price>220.9600</service_extended_price>
                <service_period_start_date>2017-08-01T00:00:00-04:00</service_period_start_date>
                <service_period_end_date>2017-08-31T00:00:00-04:00</service_period_end_date>
                <setup_fee>0.0000</setup_fee>
                <billing_approved_by>, Dominic</billing_approved_by>
                <narrative_billing_approved_by> Kirby</narrative_billing_approved_by>
                <approved_date>2017-07-11T11:03:25.957-04:00</approved_date>
                <posted_date>2017-07-10T20:00:00-04:00</posted_date>
                <non_overage_retainer_line_item_tax>0.0000</non_overage_retainer_line_item_tax>
                <gross_amount>220.9600</gross_amount>
                <contract_type>7</contract_type>
                <department_number />
                <effective_hourly_billing_rate>110.4800</effective_hourly_billing_rate>
                <external_product_id />
                <cost_description />
                <project_phase />
                <our_cost>91.5000</our_cost>
                <expense_description />
                <line_item_id>2</line_item_id>
                <tax_region_and_category_id>0</tax_region_and_category_id>
                <tax_region_name />
                <tax_category_name />
                <total_tax_rate_per_region_and_category>0.0000000</total_tax_rate_per_region_and_category>
                <total_tax_amount>0.00000</total_tax_amount>
                <allocation_code_id>29682901</allocation_code_id>
                <serial_number />
                <contract_period_type>m</contract_period_type>
                <service_period_type>m</service_period_type>
                <account_manager_when_posted>, Dominic</account_manager_when_posted>
            </invoice_item>
            <invoice_item>
                <invoice_item_id>3</invoice_item_id>
                <invoice_id>471</invoice_id>
                <item_name>SECURE MANAGED SERVICES: Firewall  [Aug 01, 2017 - Aug 31, 2017]</item_name>
                <item_id>9236</item_id>
                <item_date>2017-08-01T00:00:00-04:00</item_date>
                <adjusted_item_id />
                <type_of_transaction>Recurring Service</type_of_transaction>
                <allocation_code_name>Hardware as a Service</allocation_code_name>
                <allocation_code_external_number>HWAAS</allocation_code_external_number>
                <allocation_code_non_billable>No</allocation_code_non_billable>
                <allocation_code_taxable>No</allocation_code_taxable>
                <task_or_ticket_number />
                <task_or_ticket_title>Recurring Service</task_or_ticket_title>
                <ticket_contact />
                <narrative_ticket_contact />
                <adjustment_reason />
                <resource_name>, Dominic</resource_name>
                <narrative_resource_name>Dominic </narrative_resource_name>
                <resource_payroll_identifier />
                <role_name />
                <department>Operations</department>
                <project_name />
                <project_lead />
                <narrative_project_lead />
                <external_project_number />
                <internal_project_number />
                <gl_code_desc />
                <gl_code_name />
                <contract_name>Metro  2017</contract_name>
                <external_contract_number />
                <worked_hours>0.0000</worked_hours>
                <non_billable_hours>0.0000</non_billable_hours>
                <billable_hours>0.0000</billable_hours>
                <hourly_billing_rate>6.9200</hourly_billing_rate>
                <extended_price>6.9200</extended_price>
                <time_entry_summary_notes />
                <quantity>1.0000</quantity>
                <expense_type />
                <installed_product_name />
                <subscription_name />
                <subscription_desc />
                <subscription_cost>0.00</subscription_cost>
                <milestone_title />
                <milestone_description />
                <milestone_amount>0.0000</milestone_amount>
                <service_or_bundle_id>64</service_or_bundle_id>
                <service_name>SECURE MANAGED SERVICES: Firewall TZ300</service_name>
                <service_invoice_description>SonicWALL TZ300 Managed Firewall</service_invoice_description>
                <service_units>1</service_units>
                <service_unit_price>6.9200</service_unit_price>
                <service_extended_price>6.9200</service_extended_price>
                <service_period_start_date>2017-08-01T00:00:00-04:00</service_period_start_date>
                <service_period_end_date>2017-08-31T00:00:00-04:00</service_period_end_date>
                <setup_fee>0.0000</setup_fee>
                <billing_approved_by>, Dominic</billing_approved_by>
                <narrative_billing_approved_by>Dominic </narrative_billing_approved_by>
                <approved_date>2017-07-11T11:03:25.957-04:00</approved_date>
                <posted_date>2017-07-10T20:00:00-04:00</posted_date>
                <non_overage_retainer_line_item_tax>0.0000</non_overage_retainer_line_item_tax>
                <gross_amount>6.9200</gross_amount>
                <contract_type>7</contract_type>
                <department_number />
                <effective_hourly_billing_rate>6.9200</effective_hourly_billing_rate>
                <external_product_id />
                <cost_description />
                <project_phase />
                <our_cost>46.0000</our_cost>
                <expense_description />
                <line_item_id>3</line_item_id>
                <tax_region_and_category_id>0</tax_region_and_category_id>
                <tax_region_name />
                <tax_category_name />
                <total_tax_rate_per_region_and_category>0.0000000</total_tax_rate_per_region_and_category>
                <total_tax_amount>0.00000</total_tax_amount>
                <allocation_code_id>29683499</allocation_code_id>
                <serial_number />
                <contract_period_type>m</contract_period_type>
                <service_period_type>m</service_period_type>
                <account_manager_when_posted>, Dominic</account_manager_when_posted>
            </invoice_item>
        </invoice>
    </account>
</invoice_batch_generic>

Essentially, I need to get certain data out of this XML: 本质上,我需要从此XML中获取某些数据:

  • invoice_number 发票号码
  • total_tax_rate_per_category_and_region total_tax_rate_per_category_and_region
  • total_tax_ammount total_tax_ammount
  • And then for each invoice_item I need to make an array: 然后,对于每个invoice_item,我需要创建一个数组:
  • item_name 项目名称
  • allocation_code_external_number location_code_external_number
  • quantity 数量
  • hourly_billing_rate hourly_billing_rate
  • service_unit_price service_unit_price

Unfortunately, my XML parsing experience is nonexistent. 不幸的是,我没有XML解析经验。 This API feeds everything else as easy to parse objects... I'm not asking for someone to write this for me, just was hoping to get a pointer in the right direction. 该API可以轻松解析对象,从而提供了其他所有内容……我不是要有人为我编写此文件,只是希望获得指向正确方向的指针。 Here is where I make a feeble attempt to parse some of the items: 这是我在尝试解析某些项目时的尝试:

//THIS IS WHERE WE PULL THE XML FROM OUR API
$xmlMarkup = $AT_Client->getInvoiceMarkup($_GET['Invoice'], 'XML');
$xmlMarkupResult = $xmlMarkup->GetInvoiceMarkupResult;

//THIS IS WHERE I WANT TO PARSE THINGS INTO VALUES THAT I CAN FEED INTO XERO

$dom = new DomDocument("1.0", "ISO-8859-1");
$dom->loadXml{$xmlMarkupResult};
$xpath = new DOMXPath($dom);

$itemList = array();
$itemNodes = $xpath->query('//account/invoice/invoice_item');
for($i=0;$i<$itemNodes->length;$i++) {
    $itemList[] = $itemNodes->item($i)->nodeValue;
}

print_r($itemList);

Any guidance would be greatly appreciated! 任何指导将不胜感激!

On of the most powerful parts of the DOM extension, is its integration with XPath - in fact, DomXPath is far more powerful then the SimpleXML equivalent. 它与XPath集成是DOM扩展最强大的部分-实际上,DomXPath的功能远比等效的SimpleXML更强大。 This example seems quite complex, but in actuality it shows just how flexible the DOM XPath functionality can be. 这个例子似乎很复杂,但是实际上它显示了DOM XPath功能的灵活性。

$dom = new DOMDocument("1.0", "UTF-8");
$dom->preserveWhiteSpace = false;

$dom->loadXml($xmlMarkupResult);
$xpath = new DOMXPath($dom);
$xpath->registerNamespace("ns", "http://tempuri.org/invoice_batch_generic.xsd");

$rootNode = $xpath->query('/ns:invoice_batch_generic')->item(0);

// Invoice data
$invoiceNumber = $xpath->query('ns:account/ns:invoice/ns:invoice_number', $rootNode)->item(0)->nodeValue;
$taxRate = $xpath->query('ns:taxregioncategory/ns:total_tax_rate_per_category_and_region', $rootNode)->item(0)->nodeValue;
$totalTaxAmount = $xpath->query('ns:taxregioncategory/ns:total_tax_amount', $rootNode)->item(0)->nodeValue;

// Invoice items
$itemList = array();
$invoiceItemNodes = $xpath->query('ns:account/ns:invoice/ns:invoice_item', $rootNode);

/* @var $invoiceItemNode DOMNode */
foreach ($invoiceItemNodes as $invoiceItemNode) {
    $row = [];

    /* @var $field DOMNode */
    foreach ($invoiceItemNode->childNodes as $field) {
        $row[$field->tagName] = $field->nodeValue;
    }
    $itemList[] = $row;
}

print_r($itemList);

Using SimpleXML makes accessing the data more straightforward and (IMHO) logical. 使用SimpleXML使访问数据更加直接和逻辑化。 As this is a fairly straightforward structure, you can use something like... 由于这是一个相当简单的结构,因此您可以使用...

$xml = simplexml_load_file("t1.xml");

foreach ($xml->account->invoice as $invoice) {
    echo "Invoice id:".$invoice->invoice_id."\n";
    foreach ( $invoice->invoice_item as $item ) {
        echo "total_tax_rate_per_region_and_category:".
                (string)$item->total_tax_rate_per_region_and_category."\n";
        echo "total_tax_amount:".
                (string)$item->total_tax_amount."\n";
    }
}

As you can see, the load_file just reads the data in and then you can use the various levels of data as though accessing the elements of an object. 如您所见,load_file只是读取数据,然后您可以使用各种级别的数据,就像访问对象的元素一样。 I hope that this is enough for you to start off with. 我希望这足以让您开始。

One thing I do point out is that when accessing an element, the cast to (string) returns the value of the element, whereas simply using the elements name is an object. 我要指出的一件事是,访问元素时,强制转换为(string)返回元素的值,而仅使用元素名称就是一个对象。

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

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