0

I've never used xpath before and it's driving me batty. I have the following XML:

<entry>
 <updated>2018-02-20</updated>
  <api:related>
   <api:object>
    <api:ever-approved>true</api:ever-approved>
    <api:reporting-date-1>2017-12-31</api:reporting-date-1>
    <api:repository-items>
     <api:repository-item repository-id="1">
      <api:public-url>http://url.com</api:public-url>
      <api:content-file-count>1</api:content-file-count>
      <api:licence-file-count>1</api:licence-file-count>
      <api:status>accepted</api:status>
     </api:repository-item>
    </api:repository-items>
    <api:all-labels type="keyword-list">
     <api:keywords>
      <api:keyword>Africa</api:keyword>
      <api:keyword>Economy</api:keyword>
     </api:keywords>
    </api:all-labels>
  </api:object>
</api:related>

...which repeats in that structure. I just need to write some PHP to check whether "api:repository-items" - or any child node within it - exists for each entry. I can do this successfully for:

  • api:ever-approved
  • api:reporting-date-1
  • first api:keyword

by doing variations of:

foreach ( $this->xml->xpath( 'api:related/api:object/api:all-labels/api:keywords/api:keyword[1]' ) as $field ) {
        $this->properties['xxx'] = $field;
            }

 if ( isset( $this->properties['xxx'] ) ){
            return $this->properties['xxx'];
        } else {
            return 'nada';
        }

And that works fine. However, I cannot traverse to anything in the repository-items - I only get 'nada'.

I have tried:

  • 'api:related/api:object/api:repository-items/api:repository-item/api:status'
  • 'api:related/api:object/api:repository-items/api:repository-item/api:content-file-count'
  • 'api:related/api:object/api:repository-items/api:repository-item'
  • 'api:related/api:object/api:repository-items'
  • 'api:related/api:object//api:status'

What am I doing wrong - and any other suggestions?! Thanks!

JohnG
  • 486
  • 3
  • 22
  • You haven't shown any namespace bindings for the "api" prefix. Since incorrect namespace bindings are a common source of XPath problems, this means we can't verify that you got this right. – Michael Kay Aug 17 '18 at 14:21

1 Answers1

1

If I understood the XML correctly, this is the correct XPATH:

'//entry//api:repository-items'

The //entry searches for the relative path to nodes called entry in the XML, while //api:repository-items searches for the relative path on nodes called api:repository-items that are nested on the nodes found on //entry.

I strongly recommend reading the w3schools XPATH guide. It's a great guide containing all the information you should need about XPATHs with some graphic examples, and it's not very long.

Lucas Wieloch
  • 818
  • 7
  • 19
  • 1
    Thanks - but you've missed the point slightly - I've already accounted for the entry node within $this: as I say, the path "api:related/api:object/api:all-labels/api:keywords/api:keyword[1]" works perfectly. I'm trying to understand why that WOULD, but "api:related/api:object/api:repository-items/api:repository-item/api:content-file-count" - and indeed "//api:repository-items" wouldn't. (Oh - and I have indeed already read the w3schools XPATH guide - it's great, but hasn't helped me here!) – JohnG Aug 17 '18 at 13:38
  • I misinterpreted the question indeed, sorry. Still, the xpath isn't wrong, and if your XML structure is like that across the document those xpath's you provided on 'what i've tried' section should also work fine. I guess that the problem is on how you're using the xpath result on your PHP code? Unfortunately I can't help you with that right now, I'll try to edit this answer later. – Lucas Wieloch Aug 17 '18 at 13:54
  • Thanks Lucas - that's reassuring... I think the actual problem lies with the XML I've been given. – JohnG Aug 17 '18 at 16:19