отображать данные из XML с помощью php simplexml

#php #xml #simplexml

#php #xml — файл #simplexml #xml

Вопрос:

У меня есть фрагмент XML, который выглядит следующим образом

 <records count="2">
  <record>
    <firstname>firstname</firstname>
    <middlename>middlename</middlename>
    <lastname>lastname</lastname>
    <namesuffix/>
    <address>
      <street-number>demo</street-number>
      <street-pre-direction/>
      <street-name>demo</street-name>
      <street-post-direction/>
      <street-suffix>demo</street-suffix>
      <city>demo</city>
      <state>NY</state>
      <zip>demo</zip>
      <zip4>demo</zip4>
      <county>demo</county>
    </address>
    <phonenumberdetails>
      <phonenumber>demo</phonenumber>
      <listed>demo</listed>
      <firstname>demo</firstname>
    </phonenumberdetails>
    <dob day="" month="" year=""/>
    <age/>
    <date-first month="10" year="1999"/>
    <date-last month="04" year="2011"/>
  </record>
  <record>
    <firstname>firstname</firstname>
    <middlename>middlename</middlename>
    <lastname>lastname</lastname>
    <namesuffix/>
    <address>
      <street-number>demo</street-number>
      <street-pre-direction/>
      <street-name>demo</street-name>
      <street-post-direction/>
      <street-suffix>demo</street-suffix>
      <city>demo</city>
      <state>NY</state>
      <zip>demo</zip>
      <zip4>demo</zip4>
      <county>demo</county>
    </address>
    <phonenumberdetails>
      <phonenumber>demo</phonenumber>
      <listed>demo</listed>
      <firstname>demo</firstname>
    </phonenumberdetails>
    <dob day="" month="" year=""/>
    <age/>
    <date-first month="10" year="1999"/>
    <date-last month="04" year="2011"/>
  </record>
</records>
  

Теперь я смог получить все данные в PHP с использованием SimpleXML, за исключением элементов date-first и date-last. Я использовал код, приведенный ниже

 $dateFirst           = 'date-first';
$dateLast            = 'date-last';
$streetNumber        = 'street-number';
$streetPreDirection  = 'street-pre-direction';
$streetName          = 'street-name';
$streetPostDirection = 'street-post-direction';
$streetSuffix        = 'street-suffix';
$unitDesignation     = 'unit-designation';
$unitNumber          = 'unit-number';

foreach ($reportDataXmlrecords->records->record as $currentRecord) {
    echo $currentRecord->$dateFirst['month'].'/'.$currentRecord->$dateFirst['year'];
    echo $currentRecord->$dateLast['month'].'/'.$currentRecord->$dateLast['year'];
    echo $currentRecord->address->$streetNumber;
    $currentRecord->address->$streetName; // ......and so on 
}
  

где $reportDataXmlrecords — часть объекта SimpleXML из родительского узла

Но первые два echo ничего не печатают, а все остальные печатаются правильно, в частности, я не могу получить доступ к данным в

 <date-first month="10" year="1999"/>
<date-last month="04" year="2011"/>
  

Также для отладки, если я делаю

 print_r($currentRecord->$dateFirst);
  

он печатает

 SimpleXMLElement Object ( 
    [@attributes] => Array ( [month] => 10 [year] => 1999 ) 
)
  

Мы были бы очень признательны за любую помощь. Спасибо.

Комментарии:

1. Я предполагаю, что для этого вопроса потребуется некоторая помощь в форматировании.

2. что вы получите, если вместо echo вы добавите var_dump date-first и date-last?

3. @GordonM Если я это сделаю var_dump($currentRecord->$dateFirst); , я получу object(SimpleXMLElement)#32 (1) { ["@attributes"]=> array(2) { ["month"]=> string(2) "10" ["year"]=> string(4) "1999" } }

Ответ №1:

Ваша проблема заключается в том, когда вы делаете

 $currentRecord->$dateFirst['month']
  

PHP сначала оценит $dateFirst['month'] в целом, прежде чем пытаться использовать его как свойство

 $dateFirst = 'date-first';
var_dump( $dateFirst['month'] ); // gives "d"
  

поскольку к строкам можно получить доступ с помощью смещения с обозначением массива, но нецелочисленные смещения преобразуются в целое число, и поскольку преобразование ‘month’ в integer равно 0, вы пытаетесь сделать $currentRecord->d :

 $xml = <<< XML
<record>
    <date-first month="jan"/>
    <d>foo</d>
</record>
XML;

$record = simplexml_load_string($xml);
$var    = 'date-first';
echo $record->$var['month']; // foo
  

Вы можете получить доступ к свойствам, разделенным дефисами, с помощью фигурных скобок:

 $record->{'date-first'}['month'] // jan
  

Что касается примечания, когда XML, показанный в вашем вопросе, действительно является XML, который вы загружаете с помощью SimpleXML, например, когда <records> является корневым узлом, тогда выполните

 $reportDataXmlrecords->records->record
  

не может работать, потому что $reportDataXmlrecords это уже корневой узел, и вам пришлось бы опустить ->records , если вы хотите выполнить итерацию по элементам записи в нем.

Комментарии:

1. правильно, <records> не является корневым узлом, я добавлю исправление к вопросу. И спасибо за отличный ответ, это здорово, я узнал кое-что новое. Просто чтобы упомянуть, $record->{'dateFirst'}['month'] // jan я думаю, вы имели в виду $record->{'date-first'}['month'] // jan , что второй экземпляр сработал для меня. Возможно, это была опечатка