1
votes

I am using xpath to find content from a epg-file, but for this source, my code simply won't work. And now i have come to the point that i cant solve this myself. The XML looks like this (as you see, 2 namespaces, v3 and v31).

<?xml version="1.0" encoding="UTF-8"?>
<v3:schedule timestamp="2017-05-12T16:11:06.595Z" xmlns:v3="http://common.tv.se/schedule/v3_1">
<v3:from>2017-05-12T22:00:00.000Z</v3:from>
<v3:to>2017-05-13T22:00:00.000Z</v3:to>
...
<v3:contentList>
<v31:content timestamp="2017-05-12T16:11:06.595Z" xmlns:v31="http://common.tv.se/content/v3_1">
  <v31:contentId>content.1375706-006</v31:contentId>
  <v31:seriesId>series.40542</v31:seriesId>
  <v31:seasonNumber>3</v31:seasonNumber>
  <v31:episodeNumber>6</v31:episodeNumber>
  <v31:numberOfEpisodes>8</v31:numberOfEpisodes>
  <v31:productionYear>2017</v31:productionYear>
  ...
  <v3:eventList>
  <v31:event timestamp="2017-05-12T16:11:06.595Z" xmlns:v31="http://common.tv.se/event/v3_1">
  <v31:eventId>event.26072881</v31:eventId>
  <v31:channelId>channel.24</v31:channelId>
  <v31:rerun>true</v31:rerun>
  <v31:live>false</v31:live>
  <v31:hidden>false</v31:hidden>
  <v31:description/>
  <v31:timeList>
    <v31:time type="public">
      <v31:startTime>2017-05-12T22:55:00.000Z</v31:startTime>
      <v31:endTime>2017-05-12T23:55:00.000Z</v31:endTime>
      <v31:duration>01:00:00:00</v31:duration>
    </v31:time>
  </v31:timeList>
  <v31:contentIdRef>content.1375706-006</v31:contentIdRef>
  <v31:materialIdRef>material.1010161108005267221</v31:materialIdRef>
  <v31:previousEventList/>
  <v31:comingEventList/>
  </v31:event>
  ...
  <v3:materialList>
  <v31:material timestamp="2017-05-12T16:11:06.595Z" xmlns:v31="http://common.tv.se/material/v3_1">
  <v31:materialId>material.1010161108005267221</v31:materialId>
  <v31:contentIdRef>content.1375706-006</v31:contentIdRef>
  <v31:materialType>tx</v31:materialType>
  <v31:videoFormat>576i</v31:videoFormat>
  <v31:audioList>
    <v31:format language="unknown">stereo</v31:format>
  </v31:audioList>
  <v31:aspectRatio>16:9</v31:aspectRatio>
  <v31:materialReferenceList>
  </v31:materialReferenceList>
  </v31:material>
...

And the "contentIdRef" is what keeps the different elements (event and material) together. And i want to find all the data, based on contentIdRef.

I have used this (in php):

$parent = $this->xmldata->xpath('//v31:event/v31:contentIdRef[.="content.1375706-006"]/parent::*')

and i have also tried

$parent = $this->xmldata->xpath('//v31:event/v31:contentIdRef[.="content.1375706-006"]/parent::*/child::*');

But, the first alternative just (with print_r) returns v31:event "timestamp"

the second alternative returns 11 "simpleXMLobjects" that are empty ( why are they empty?? ), so based on the amount of objects, i think i have "hit the spot", but i can't find out why they are empty....

And yes, i have registered namespaces throughout my code ( i wish it was that simple ).

TLDR; I want to 1. get all contentIds from first block (v3:contentList), 2. get all eventdata for each contentId, 3. get all materialdata for each content id...

I sincerely hope you can help :/

1

1 Answers

0
votes

Did you register prefixes for the namespaces in the Xpath expressions? Always register your own prefixes for the namespaces you're using. PHP registers the namespace definition of the current context node by default. But this can change on any element node in the document and not all prefixes might be defined on the document element.

$schedule = new SimpleXMLElement($xml);
$schedule->registerXpathNamespace('s', 'http://common.tv.se/schedule/v3_1');
$schedule->registerXpathNamespace('e', 'http://common.tv.se/event/v3_1');

$events = $schedule->xpath(
  '//e:event[e:contentIdRef = "content.1375706-006"]'
);

foreach ($events as $event) {
  echo $event->asXml(), "\n\n";
}

Or with DOM:

$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('s', 'http://common.tv.se/schedule/v3_1');
$xpath->registerNamespace('e', 'http://common.tv.se/event/v3_1');

$events = $xpath->evaluate('//e:event');
foreach ($events as $event) {
  echo $document->saveXml($event), "\n\n";
}