2

This is my xml:

<?xml version="1.0"?>
<data>
    <client_name>Awesome Client</client_name>
    <account_number/>
    <date_created>02/12/2016</date_created>
    <form_number>4126</form_number>
    <customer_po/>
    <terms_name>Credit Card</terms_name>
    <date_shipped>12/31/1969</date_shipped>
    <billing_contact_email/>
    <billing_contact_address_line_1/>
    <billing_contact_address_line_2/>
    <billing_contact_address_line_3/>
    <billing_contact_address_line_4/>
    <billing_contact_address_city/>
    <billing_contact_address_state>British Columbia</billing_contact_address_state>
    <billing_contact_address_postal/>
    <billing_contact_address_country>Canada</billing_contact_address_country>
    <shipping_contact_address_line_1/>
    <shipping_contact_address_line_2/>
    <shipping_contact_address_line_3/>
    <shipping_contact_address_line_4/>
    <shipping_contact_address_city/>
    <shipping_contact_address_state>British Columbia</shipping_contact_address_state>
    <shipping_contact_address_postal/>
    <shipping_contact_address_country>Canada</shipping_contact_address_country>
    <billing_contact_first_name>another</billing_contact_first_name>
    <billing_contact_last_name>client</billing_contact_last_name>
    <client_rep_full_name>Rob Montebelli</client_rep_full_name>
    <order_rep_full_name>Mark Graham</order_rep_full_name>
    <job_name>77777</job_name>
    <job_number>2620</job_number>
    <event_type>Donor Gift</event_type>
    <due_date>02/12/2016</due_date>
    <shipping_method/>
    <currency>CAD</currency>
    <total_taxes>0.00</total_taxes>
    <total_subtotal>1,760.16</total_subtotal>
    <total>1,760.16</total>
    <items>
        <item0>
            <taxes>
                <0>E</0>
            </taxes>
            <title>1889-24</title>
            <quantity>6</quantity>
            <description>Carhartt (R) Signature Utility Duffel; TBD TBD</description>
            <unit_price>159.32</unit_price>
        </item0>
        <item1>
            <taxes>
                <0>E</0>
            </taxes>
            <title>0022-56</title>
            <quantity>12</quantity>
            <description>Zoom (TM) DayTripper Sling Compu-Messenger; TBD TBD</description>
            <unit_price>67.02</unit_price>
        </item1>
    </items>
</data>

My code:

$xml_data = new SimpleXMLElement('<?xml version="1.0"?><data></data>');
array_to_xml($invoice, $xml_data);
$xml = $xml_data->asXML();

$domxml = new DOMDocument('1.0');
$domxml->preserveWhiteSpace = false;
$domxml->formatOutput = true;
$domxml->loadXML($xml);
$xml_string = $domxml->saveXML();

I think the xml is in the right format so why is this failing?

Edit:

Here is the dynamic array before converted into xml using XMLSimpleElement, is there anyway to remove <0> before converted into xml?:

Array
(
    [invoices] => Array
        (
            [0] => Array
                (
                    [client_name] => Awesome Client
                    [account_number] => 
                    [date_created] => 02/11/2016
                    [form_number] => 4104
                    [customer_po] => 
                    [terms_name] => Credit Card
                    [date_shipped] => 12/31/1969
                    [billing_contact_email] => 
                    [billing_contact_address_line_1] => 
                    [billing_contact_address_line_2] => 
                    [billing_contact_address_line_3] => 
                    [billing_contact_address_line_4] => 
                    [billing_contact_address_city] => 
                    [billing_contact_address_state] => British Columbia
                    [billing_contact_address_postal] => 
                    [billing_contact_address_country] => Canada
                    [shipping_contact_address_line_1] => 
                    [shipping_contact_address_line_2] => 
                    [shipping_contact_address_line_3] => 
                    [shipping_contact_address_line_4] => 
                    [shipping_contact_address_city] => 
                    [shipping_contact_address_state] => British Columbia
                    [shipping_contact_address_postal] => 
                    [shipping_contact_address_country] => Canada
                    [billing_contact_first_name] => another
                    [billing_contact_last_name] => client
                    [client_rep_full_name] => Rob Montebelli
                    [order_rep_full_name] => Mark Graham
                    [job_name] => 5010
                    [job_number] => 2598
                    [event_type] => Donor Gift
                    [due_date] => 02/11/2016
                    [shipping_method] => 
                    [currency] => CAD
                    [total_taxes] => 0.00
                    [total_subtotal] => 1,760.16
                    [total] => 1,760.16
                    [items] => Array
                        (
                            [0] => Array
                                (
                                    [taxes] => Array
                                        (
                                            [0] => E
                                        )

                                    [title] => 1889-24
                                    [quantity] => 6
                                    [description] => Carhartt (R) Signature Utility Duffel; TBD TBD
                                    [unit_price] => 159.32
                                )

                            [1] => Array
                                (
                                    [taxes] => Array
                                        (
                                            [0] => E
                                        )

                                    [title] => 0022-56
                                    [quantity] => 12
                                    [description] => Zoom (TM) DayTripper Sling Compu-Messenger; TBD TBD
                                    [unit_price] => 67.02
                                )

                        )

                )

        )

)
Blkc
  • 560
  • 7
  • 29
  • 3
    The `<0>` is throwing it off, that is an invalid element name. – chris85 Feb 12 '16 at 14:51
  • @chris85 Oh I see, is there anyway to remove it using a function or I should remove it from the array before I convert it into xml? – Blkc Feb 12 '16 at 14:52
  • Remove the element or the warning? – chris85 Feb 12 '16 at 14:53
  • @chris85 remove the <0> and just leave with E within < taxes>? Maybe something like a regex? – Blkc Feb 12 '16 at 14:54
  • @chris85 Thanks alot! – Blkc Feb 12 '16 at 15:02
  • If you are generating the XML, then you should fix the routine that is generating it not to output such invalid elements. In other words, the bug is not in the code shown, but in the `array_to_xml` functions. – IMSoP Feb 12 '16 at 15:13
  • @IMSoP I see. I was using the Hanmant's answer in http://stackoverflow.com/questions/1397036/how-to-convert-array-to-simplexml to convert into xml – Blkc Feb 12 '16 at 15:22
  • 1
    @Blkc Aha. Right under that answer, the first comment, highlighted as useful by 24 users, says "However, this has the limitation that with numerically keyed arrays, it generates malformed XML. <0> <1> <2> are not valid node names." – IMSoP Feb 12 '16 at 15:53

2 Answers2

3

As mentioned in the comments the issue is with your number elements, <0>. That is an invalid element name. You could manually modify the XML file if this is a static file, remove or rename, use a regex, or suppress the error. If you suppress you will have to remember that in the future, it will never tell you about errors.

Regex approach:

$invoice = preg_replace('~<(/?\d)~', '<number$1', $invoice);

Regex demo: https://regex101.com/r/pZ3sJ4/1

One suppression option:

libxml_use_internal_errors(true);
$domxml->loadXML($invoice);
libxml_clear_errors();

With this approach you can still retrieve the errors pretty easily.

e.g.

libxml_use_internal_errors(true);
$domxml->loadXML($invoice);
$xml_string = $domxml->saveXML();
$errors = libxml_get_errors();
foreach ($errors as $error) {
    echo $error->message;
}
libxml_clear_errors();

Second suppression option:

@$domxml->loadXML($invoice);

yuck..

Third simple non-programming option, just edit the file manually:

<item1>
            <taxes><name0>E</name0></taxes>
            <title>0022-56</title>
            <quantity>12</quantity>
            <description>Zoom (TM) DayTripper Sling Compu-Messenger; TBD TBD</description>
            <unit_price>67.02</unit_price>
        </item1>
chris85
  • 23,846
  • 7
  • 34
  • 51
  • I applied the regex to $xml but I am having this error: `DOMDocument::loadXML(): Opening and ending tag mismatch: number0 line 2 and taxes in Entity` – Blkc Feb 12 '16 at 15:31
  • The problem was the closing tag wasn't replaced with so I used 2 regex instead of 1. Thanks again. – Blkc Feb 12 '16 at 15:46
  • This answer is great if you have no control over the original XML. If you are generating the XML yourself, the answer is not to mangle the result, but to fix your generator to **create valid XML in the first place**. – IMSoP Feb 12 '16 at 15:55
  • Oh yea, forgot about that, move the `/` inside the capture group and should work. Ill update answer. – chris85 Feb 12 '16 at 16:27
2

Element names must start with a letter or underscore

Watch http://www.w3schools.com/xml/xml_elements.asp for more information

change

<taxes> 
  <0> E </0> 
</taxes> 

to

<taxes> 
  <t0> E </t0> 
</taxes> 

for example

John Smith
  • 319
  • 3
  • 11