2

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.

Christian
  • 328
  • 3
  • 14
  • For future questions, please try to provide a [mcve] - the XML you've given is incomplete, making it harder for people to give you tested examples in answers. – IMSoP Jun 02 '21 at 19:00
  • Just updated to give a complete XML snippet. – Christian Jun 02 '21 at 19:08
  • 1
    @miken32 [Your proposed duplicate](https://stackoverflow.com/questions/595946/parse-xml-with-namespace-using-simplexml) is mostly about XPath, which this question doesn't mention; none of its answers explain correct use of ->children(), which this question identified as the key method. (A few of them mention it, but use it really badly.) I have attempted to write a more complete reference Q&A here: https://stackoverflow.com/questions/44894426/reference-how-do-i-handle-namespaces-tags-and-attributes-with-colon-in-in-si but in this case I felt there was something more specific to be explained. – IMSoP Jun 02 '21 at 20:50
  • There are a few answers that use `children()` with a namespace value such as [this one](https://stackoverflow.com/a/21568058/1255289) but I'm fine leaving it as is. It's not a bad question by any means, just seemed like something that has been asked before. – miken32 Jun 02 '21 at 20:54
  • 1
    @miken32 Just for the record, that answer is still relying on the local alias ('event') rather than the actual namespace URI ('http://www.webex.com/schemas/2002/06/service/event'), so it is not good advice. – IMSoP Jun 08 '21 at 14:10

2 Answers2

3

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;
IMSoP
  • 89,526
  • 13
  • 117
  • 169
1

Since you're looking for getting at a particular namespace value blend:marketingvalue. In that case you could get it directly through XPath.

echo $xml->xpath('//blend:marketingvalue')[0]; //google.com

Notice: xpath returns an array of objects, So Since you have one value access it by first position [0]. However if there are others you can use foreach.

foreach ($xml->xpath('//blend:marketingvalue') as $value) {
    echo "marketing value: ". $value ."<BR>";
}
XMehdi01
  • 5,538
  • 2
  • 10
  • 34