【问题标题】:Can you help me parse this XML w/ PHP?你能帮我用 PHP 解析这个 XML 吗?
【发布时间】:2017-12-23 12:28:52
【问题描述】:

我正在尝试为我们的 PSA 软件编写付款和 Xero 集成。感谢这里的帮助,计费部分进展顺利。现在有趣的部分来了:将发票数据从 PSA 的 API 解析为我可以输入 Xero 的可用数据...

这是来自 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>

基本上,我需要从这个 XML 中获取某些数据:

  • invoice_number
  • total_tax_rate_per_category_and_region
  • total_tax_ammount
  • 然后我需要为每个 invoice_item 创建一个数组:
  • item_name
  • allocation_code_external_number
  • 数量
  • hourly_billing_rate
  • service_unit_price

不幸的是,我的 XML 解析经验是不存在的。这个 API 提供所有其他东西,就像解析对象一样容易......我不是要求有人为我写这个,只是希望得到一个正确方向的指针。这是我尝试解析一些项目的地方:

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

任何指导将不胜感激!

【问题讨论】:

  • print_r($itemList); 显示什么
  • 如果您不熟悉 XML,我强烈推荐 SimpleXML;顾名思义,它简化了所有像这样的常见任务。请务必通读the usage examples in the manual,而不是相信print_r,在使用它时,它并不总是能告诉你正确的事情。

标签: php xml dom


【解决方案1】:

使用 SimpleXML 使访问数据更加直接和(恕我直言)合乎逻辑。由于这是一个相当简单的结构,您可以使用类似...

$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";
    }
}

如您所见,load_file 只是读取数据,然后您可以使用各种级别的数据,就像访问对象的元素一样。我希望这足以让您开始。

我要指出的一件事是,当访问一个元素时,转换为 (string) 会返回元素的值,而简单地使用元素名称就是一个对象。

【讨论】:

    【解决方案2】:

    DOM 扩展最强大的部分之一是它与 XPath 的集成——事实上,DomXPath 比 SimpleXML 等价物强大得多。这个例子看起来很复杂,但实际上它显示了 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);
    

    【讨论】:

    • 外部部分很好,但您也可以使用表达式来获取详细信息:$row = [ 'invoice_number' =&gt; $xpath-&gt;evaluate('string(invoice_id)', $invoiceItemNode), ... ]。另外检查 tagName 以验证它是一个元素节点并不优雅。使用 nodeType 或仅验证类 (if ($field instanceof DOMElement) { ...)。
    猜你喜欢
    • 2021-01-28
    • 1970-01-01
    • 2021-03-12
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-15
    相关资源
    最近更新 更多