Search code examples
phpxmlsimplexml

XML - getting value from namespace using SimpleXML


I'm having an issue getting at a particular namespace value using Simple XML.

Here's a snippet from the XML file:

<message xmlns:blend="http://www.blendlabs.com"
 xmlns:ulad="http://www.datamodelextension.org/Schema/ULAD"
 xmlns="http://www.mismo.org/residential/2009/schemas"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xlink="http://www.w3.org/1999/xlink"
 targetnamespace="http://www.mismo.org/residential/2009/schemas">
  <deal_sets>
    <deal_set>
      <deals>
        <deal>
          <loans>
            <loan loanroletype="SubjectLoan" sequencenumber="1" xlink:label="LOAN_1">
              <extension>
                <other>
                  <blend:loan xlink:label="LOAN_1_BLEND_EXTENSION">
                    <blend:marketing_items>
                      <blend:marketing_item>
                        <blend:marketingtypevalue>DirectMarketingCode</blend:marketingtypevalue>
                        <blend:marketingvalue>google.com</blend:marketingvalue>
                      </blend:marketing_item>
                    </blend:marketing_items>
                  </blend:loan>
                </other>
              </extension>
            </loan>
          </loans>
        </deal>
      </deals>
    </deal_set>
  </deal_sets>
</message>

The value I'm trying to get would be google.com from the blend:marketingvalue field at the end of the snippet.

I can access non-namespace values just fine but I don't really get how to access the nested namespace values for the blend fields.

Here is the code I am try to use:

$xml  = simplexml_load_string($body);
        
$blend = $xml->children('http://www.blendlabs.com');
        
$marketing_value = $xml->DEAL_SETS->DEAL_SET->DEALS->DEAL->LOANS->LOAN->EXTENSION->OTHER->$blend->LOAN->MARKETING_ITEMS->MARKETING_ITEM->MARKETINGVALUE;

echo $marketing_value; // just echo's nothing currently.

So I guess my question is, how do you format it to access nested objects?

Do I need to put the $blend variable in front of each object item?

Is that even how you are supposed to use the children function?

Any help would be much appreciated.


Solution

  • The children() method doesn't return some kind of token for the namespace, it returns a list of elements - the children which are in the given namespace.

    The $xml variable represents the top-level message element, which doesn't have any children in the http://www.blendlabs.com namespace, so $xml->children('http://www.blendlabs.com') will just return an empty list. You need to first navigate to the other element, and then get its children in the http://www.blendlabs.com namespace, which will include the loan element.

    Since the top level element is in the http://www.mismo.org/residential/2009/schemas namespace, you might need an extra children() call to make sure you select that first.

    You didn't provide a complete XML, so I can't test the code (I don't fancy manually writing all those close tags), but it will look something like this:

    $marketing_value = (string)
       $xml
       ->children('http://www.mismo.org/residential/2009/schemas')
       ->deal_sets->deal_set->deals->deal->loans->loan->extension->other
       ->children('http://www.blendlabs.com')
       ->loan->marketing_items->marketing_item->marketingvalue;