【问题标题】:Is there a cleaner way to achieve this XML to JSON transformation of NHS data有没有一种更简洁的方法来实现这种 XML 到 NHS 数据的 JSON 转换
【发布时间】:2019-12-27 21:29:15
【问题描述】:

我正在使用来自公共 NHS API 的位置和地址数据,它采用 XML 格式,我已将其转换为 JSON 以在我的 web 应用程序中使用。

我的代码正在运行并产生预期的结果,但是我不禁对这段代码中嵌套的 foreach 循环的数量感到畏缩。

有没有更简洁的方法来获得更高性能的相同结果?

我尝试过使用 simplexml_load_string 和许多变体,但它拒绝输出/解析包含 s:organisationSummary 数据的嵌套元素的内容。

这是 PHP 类

class XmlElement {
    public $name;
    public $attributes;
    public $content;
    public $children;
}

class GpService
{
    protected $apiKey;

    public function __construct()
    {
        $this->apiKey = env('NHS_API_KEY');
    }

    public function xmlToObject($xml) {
        $parser = xml_parser_create();
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
        xml_parse_into_struct($parser, $xml, $tags);
        xml_parser_free($parser);

        $elements = array();  // the currently filling [child] XmlElement array
        $stack = array();
        foreach ($tags as $tag) {
          $index = count($elements);
          if ($tag['type'] == "complete" || $tag['type'] == "open") {
            $elements[$index] = new XmlElement;
            $elements[$index]->name = $tag['tag'];
            $elements[$index]->attributes = (isset($tag['attributes']))?$tag['attributes']:null;
            $elements[$index]->content = (isset($tag['value']))?$tag['value']:null;
            if ($tag['type'] == "open") {  // push
              $elements[$index]->children = array();
              $stack[count($stack)] = &$elements;
              $elements = &$elements[$index]->children;
            }
          }
          if ($tag['type'] == "close") {  // pop
            $elements = &$stack[count($stack) - 1];
            unset($stack[count($stack) - 1]);
          }
        }
        return $elements[0];  // the single top-level element
    }

    public function searchByPostcode($postcode)
    {
        $postcodeRequest = new \GuzzleHttp\Client();
        $postcodeGet = $postcodeRequest->request('GET', 'https://api.nhs.uk/data/gppractices/postcode/' . $postcode . '/?distance=15', [
            'headers' => [
                'subscription-key' => $this->apiKey,
            ]
        ]);

        //Convert the XML string into an SimpleXMLElement object.
        $xmlObject = $this->xmlToObject($postcodeGet->getBody());
        $outputObject = [];

        // Absolutely insane loops to get data into the format I would like
        foreach($xmlObject->children as $key => $entry)
        {
            if($entry->name === 'entry')
            {
                foreach($entry->children as $value)
                {
                    if($value->name === 'content')
                    {
                        foreach($value->children as $objectProperty)
                        {
                            foreach($objectProperty->children as $dataItem)
                            {
                                if(is_array($dataItem->children))
                                {
                                    foreach($dataItem->children as $childKey => $childDataItem)
                                    {
                                        if($childDataItem->name == 's:addressLine')
                                        {
                                            $childDataItem->name = $childDataItem->name . $childKey;
                                        }
                                        $outputObject[$key][str_replace('s:','',strtolower($childDataItem->name))] = $childDataItem->content;
                                    }
                                }
                                else
                                {
                                    $outputObject[$key][str_replace('s:','',strtolower($dataItem->name))] = $dataItem->content;
                                }
                            }
                        }
                    }
                }
            }
        }

        return $outputObject;
    }
}

这是 XML 数据:

<feed xmlns:s="https://api.nhs.uk/data/services" xmlns="https://www.w3.org/2005/Atom">
  <title type="text">NHS website - GP Practices Near Postcode - LE2 1DA - Within 15km</title>
  <id>https://api.nhs.uk/data/gppractices/postcode/le21da?range=15</id>
  <rights type="text">© Crown Copyright 2009</rights>
  <updated>2019-08-22T15:04:20+01:00</updated>
  <category term="Search"/>
  <logo>https://www.nhs.uk/nhscwebservices/documents/logo1.jpg</logo>
  <author>
    <name>NHS website</name>
    <uri>https://www.nhs.uk</uri>
    <email>webservices@nhschoices.nhs.uk</email>
  </author>
  <link rel="self" type="application/xml" title="NHS website - GP Practices Near Postcode - LE2 1DA - Within 15km" href="https://api.nhs.uk/data/gppractices/postcode/LE21DA&amp;range=15"/>
  <link rel="first" type="application/xml" title="first" length="1000" href="https://api.nhs.uk/data/gppractices/postcode/LE21DA&amp;range=15&amp;page=1"/>
  <link rel="next" type="application/xml" title="next" length="1000" href="https://api.nhs.uk/data/gppractices/postcode/LE21DA&amp;range=15&amp;page=2"/>
  <link rel="last" type="application/xml" title="last" length="1000" href="https://api.nhs.uk/data/gppractices/postcode/LE21DA&amp;range=15&amp;page=10"/>
  <tracking xmlns="https://api.nhs.uk/data/services">&lt;img style="border: 0; width: 1px; height: 1px;" alt="" src="https://statse.webtrendslive.com/dcs2221tai1ckz5huxw0mfq86_1m2w/njs.gif?dcsuri=/organisations%2fgppractices%2fpostcode%2fLE21DA&amp;amp;wt.cg_s=OrganisationData&amp;amp;wt.cg_n=syndication&amp;synduserid=7a6ea2a0-8dec-11e9-8e02-f5191ebd3281&amp;syndreviewdate=22-08-2019T14:04&amp;synduserid=7a6ea2a0-8dec-11e9-8e02-f5191ebd3281&amp;syndreviewdate=22-08-2019T14:04"/&gt;</tracking>
  <s:SearchCoords>52.6299,-1.11502</s:SearchCoords>
  <entry>
    <id>https://api.nhs.uk/data/gppractices/4863</id>
    <title type="text">Highfields Surgery (R Wadhwa)</title>
    <updated>2019-08-22T14:04:20Z</updated>
    <link rel="self" title="Highfields Surgery (R Wadhwa)" href="https://api.nhs.uk/data/gppractices/4863"/>
    <link rel="alternate" title="Highfields Surgery (R Wadhwa)" href="https://www.nhs.uk/Services/GP/Overview/DefaultView.aspx?id=42231"/>
    <content type="application/xml">
      <s:organisationSummary>
        <s:name>Highfields Surgery (R Wadhwa)</s:name>
        <s:odsCode>C82116</s:odsCode>
        <s:address>
          <s:addressLine>25 Severn Street</s:addressLine>
          <s:addressLine>Leicester</s:addressLine>
          <s:addressLine>Leicestershire</s:addressLine>
          <s:postcode>LE2 0NN</s:postcode>
        </s:address>
        <s:contact type="General">
          <s:telephone>01162543253</s:telephone>
        </s:contact>
        <s:geographicCoordinates>
          <s:longitude>-1.11859357357025</s:longitude>
          <s:latitude>52.6293983459473</s:latitude>
        </s:geographicCoordinates>
        <s:Distance>0.247038430918239</s:Distance>
      </s:organisationSummary>
    </content>
  </entry>
  <entry>
    <id>https://api.nhs.uk/data/gppractices/4901</id>
    <title type="text">Dr R Kapur &amp; Partners</title>
    <updated>2019-08-22T14:04:20Z</updated>
    <link rel="self" title="Dr R Kapur &amp; Partners" href="https://api.nhs.uk/data/gppractices/4901"/>
    <link rel="alternate" title="Dr R Kapur &amp; Partners" href="https://www.nhs.uk/Services/GP/Overview/DefaultView.aspx?id=36753"/>
    <content type="application/xml">
      <s:organisationSummary>
        <s:name>Dr R Kapur &amp; Partners</s:name>
        <s:odsCode>C82659</s:odsCode>
        <s:address>
          <s:addressLine>St Peters Health Centre</s:addressLine>
          <s:addressLine>Sparkenhoe Street</s:addressLine>
          <s:addressLine>Leicester</s:addressLine>
          <s:addressLine>Leicestershire</s:addressLine>
          <s:postcode>LE2 0TA</s:postcode>
        </s:address>
        <s:contact type="General">
          <s:telephone>01162951258</s:telephone>
        </s:contact>
        <s:geographicCoordinates>
          <s:longitude>-1.11907768249512</s:longitude>
          <s:latitude>52.6310386657715</s:latitude>
        </s:geographicCoordinates>
        <s:Distance>0.30219913005026</s:Distance>
      </s:organisationSummary>
    </content>
  </entry>
  <entry>
    <id>https://api.nhs.uk/data/gppractices/4827</id>
    <title type="text">Shefa Medical Practice</title>
    <updated>2019-08-22T14:04:20Z</updated>
    <link rel="self" title="Shefa Medical Practice" href="https://api.nhs.uk/data/gppractices/4827"/>
    <link rel="alternate" title="Shefa Medical Practice" href="https://www.nhs.uk/Services/GP/Overview/DefaultView.aspx?id=38960"/>
    <content type="application/xml">
      <s:organisationSummary>
        <s:name>Shefa Medical Practice</s:name>
        <s:odsCode>C82080</s:odsCode>
        <s:address>
          <s:addressLine>St Peters Health Centre</s:addressLine>
          <s:addressLine>Sparkenhoe Street</s:addressLine>
          <s:addressLine>Leicester</s:addressLine>
          <s:addressLine>Leicestershire</s:addressLine>
          <s:postcode>LE2 0TA</s:postcode>
        </s:address>
        <s:contact type="General">
          <s:telephone>01162957835</s:telephone>
        </s:contact>
        <s:geographicCoordinates>
          <s:longitude>-1.11907768249512</s:longitude>
          <s:latitude>52.6310386657715</s:latitude>
        </s:geographicCoordinates>
        <s:Distance>0.30219913005026</s:Distance>
      </s:organisationSummary>
    </content>
  </entry>
  <entry>
    <id>https://api.nhs.uk/data/gppractices/4902</id>
    <title type="text">St Peter's Health Centre - Mansingh &amp; Partner</title>
    <updated>2019-08-22T14:04:20Z</updated>
    <link rel="self" title="St Peter's Health Centre - Mansingh &amp; Partner" href="https://api.nhs.uk/data/gppractices/4902"/>
    <link rel="alternate" title="St Peter's Health Centre - Mansingh &amp; Partner" href="https://www.nhs.uk/Services/GP/Overview/DefaultView.aspx?id=35950"/>
    <content type="application/xml">
      <s:organisationSummary>
        <s:name>St Peter's Health Centre - Mansingh &amp; Partner</s:name>
        <s:odsCode>C82660</s:odsCode>
        <s:address>
          <s:addressLine>Sparkenhoe Street</s:addressLine>
          <s:addressLine>Leicester</s:addressLine>
          <s:addressLine>Leicestershire</s:addressLine>
          <s:postcode>LE2 0TA</s:postcode>
        </s:address>
        <s:contact type="General">
          <s:telephone>01162957827</s:telephone>
        </s:contact>
        <s:geographicCoordinates>
          <s:longitude>-1.11907768249512</s:longitude>
          <s:latitude>52.6310386657715</s:latitude>
        </s:geographicCoordinates>
        <s:Distance>0.30219913005026</s:Distance>
      </s:organisationSummary>
    </content>
  </entry>
  <entry>
    <id>https://api.nhs.uk/data/gppractices/4848</id>
    <title type="text">Al-Waqas Medical Centre</title>
    <updated>2019-08-22T14:04:20Z</updated>
    <link rel="self" title="Al-Waqas Medical Centre" href="https://api.nhs.uk/data/gppractices/4848"/>
    <link rel="alternate" title="Al-Waqas Medical Centre" href="https://www.nhs.uk/Services/GP/Overview/DefaultView.aspx?id=43636"/>
    <content type="application/xml">
      <s:organisationSummary>
        <s:name>Al-Waqas Medical Centre</s:name>
        <s:odsCode>C82099</s:odsCode>
        <s:address>
          <s:addressLine>AL-Waqas Medical Practice</s:addressLine>
          <s:addressLine>91 St Peters Road</s:addressLine>
          <s:addressLine>Leicester</s:addressLine>
          <s:addressLine>Leicestershire</s:addressLine>
          <s:postcode>LE2 1DJ</s:postcode>
        </s:address>
        <s:contact type="General">
          <s:telephone>01162543003</s:telephone>
        </s:contact>
        <s:geographicCoordinates>
          <s:longitude>-1.10840618610382</s:longitude>
          <s:latitude>52.6290435791016</s:latitude>
        </s:geographicCoordinates>
        <s:Distance>0.458084198394662</s:Distance>
      </s:organisationSummary>
    </content>
  </entry>
  <entry>
    <id>https://api.nhs.uk/data/gppractices/4889</id>
    <title type="text">Community Health Centre</title>
    <updated>2019-08-22T14:04:20Z</updated>
    <link rel="self" title="Community Health Centre" href="https://api.nhs.uk/data/gppractices/4889"/>
    <link rel="alternate" title="Community Health Centre" href="https://www.nhs.uk/Services/GP/Overview/DefaultView.aspx?id=42802"/>
    <content type="application/xml">
      <s:organisationSummary>
        <s:name>Community Health Centre</s:name>
        <s:odsCode>C82643</s:odsCode>
        <s:address>
          <s:addressLine>Melbourne Centre</s:addressLine>
          <s:addressLine>Melbourne Road</s:addressLine>
          <s:addressLine>Leicester</s:addressLine>
          <s:addressLine>Leicestershire</s:addressLine>
          <s:postcode>LE2 0GU</s:postcode>
        </s:address>
        <s:contact type="General">
          <s:telephone>01162622946</s:telephone>
        </s:contact>
        <s:geographicCoordinates>
          <s:longitude>-1.11336529254913</s:longitude>
          <s:latitude>52.6338653564453</s:latitude>
        </s:geographicCoordinates>
        <s:Distance>0.462480666213577</s:Distance>
      </s:organisationSummary>
    </content>
  </entry>
  <entry>
    <id>https://api.nhs.uk/data/gppractices/4801</id>
    <title type="text">Sayeed Medical Centre</title>
    <updated>2019-08-22T14:04:20Z</updated>
    <link rel="self" title="Sayeed Medical Centre" href="https://api.nhs.uk/data/gppractices/4801"/>
    <link rel="alternate" title="Sayeed Medical Centre" href="https://www.nhs.uk/Services/GP/Overview/DefaultView.aspx?id=42819"/>
    <content type="application/xml">
      <s:organisationSummary>
        <s:name>Sayeed Medical Centre</s:name>
        <s:odsCode>C82060</s:odsCode>
        <s:address>
          <s:addressLine>352-354 East Park Road</s:addressLine>
          <s:addressLine>Leicester</s:addressLine>
          <s:addressLine>Leicestershire</s:addressLine>
          <s:postcode>LE5 5AY</s:postcode>
        </s:address>
        <s:contact type="General">
          <s:telephone>01163232030</s:telephone>
        </s:contact>
        <s:geographicCoordinates>
          <s:longitude>-1.10658276081085</s:longitude>
          <s:latitude>52.630802154541</s:latitude>
        </s:geographicCoordinates>
        <s:Distance>0.581034496166074</s:Distance>
      </s:organisationSummary>
    </content>
  </entry>
  <entry>
    <id>https://api.nhs.uk/data/gppractices/4759</id>
    <title type="text">Melbourne Street Surgery</title>
    <updated>2019-08-22T14:04:20Z</updated>
    <link rel="self" title="Melbourne Street Surgery" href="https://api.nhs.uk/data/gppractices/4759"/>
    <link rel="alternate" title="Melbourne Street Surgery" href="https://www.nhs.uk/Services/GP/Overview/DefaultView.aspx?id=36620"/>
    <content type="application/xml">
      <s:organisationSummary>
        <s:name>Melbourne Street Surgery</s:name>
        <s:odsCode>C82031</s:odsCode>
        <s:address>
          <s:addressLine>56 Melbourne Street</s:addressLine>
          <s:addressLine>Leicester</s:addressLine>
          <s:addressLine>Leicestershire</s:addressLine>
          <s:postcode>LE2 0AS</s:postcode>
        </s:address>
        <s:contact type="General">
          <s:telephone>01162536299</s:telephone>
        </s:contact>
        <s:geographicCoordinates>
          <s:longitude>-1.11437559127808</s:longitude>
          <s:latitude>52.636344909668</s:latitude>
        </s:geographicCoordinates>
        <s:Distance>0.717122615984056</s:Distance>
      </s:organisationSummary>
    </content>
  </entry>
  <entry>
    <id>https://api.nhs.uk/data/gppractices/4770</id>
    <title type="text">East Park Medical Centre - R P Pandya</title>
    <updated>2019-08-22T14:04:20Z</updated>
    <link rel="self" title="East Park Medical Centre - R P Pandya" href="https://api.nhs.uk/data/gppractices/4770"/>
    <link rel="alternate" title="East Park Medical Centre - R P Pandya" href="https://www.nhs.uk/Services/GP/Overview/DefaultView.aspx?id=40574"/>
    <content type="application/xml">
      <s:organisationSummary>
        <s:name>East Park Medical Centre - R P Pandya</s:name>
        <s:odsCode>C82037</s:odsCode>
        <s:address>
          <s:addressLine>264-266 East Park Road</s:addressLine>
          <s:addressLine>Leicester</s:addressLine>
          <s:addressLine>Leicestershire</s:addressLine>
          <s:postcode>LE5 5FD</s:postcode>
        </s:address>
        <s:contact type="General">
          <s:telephone>01162736330</s:telephone>
        </s:contact>
        <s:geographicCoordinates>
          <s:longitude>-1.10444343090057</s:longitude>
          <s:latitude>52.633544921875</s:latitude>
        </s:geographicCoordinates>
        <s:Distance>0.822717143851754</s:Distance>
      </s:organisationSummary>
    </content>
  </entry>
  <entry>
    <id>https://api.nhs.uk/data/gppractices/4834</id>
    <title type="text">Evington Medical Centre</title>
    <updated>2019-08-22T14:04:20Z</updated>
    <link rel="self" title="Evington Medical Centre" href="https://api.nhs.uk/data/gppractices/4834"/>
    <link rel="alternate" title="Evington Medical Centre" href="https://www.nhs.uk/Services/GP/Overview/DefaultView.aspx?id=36363"/>
    <content type="application/xml">
      <s:organisationSummary>
        <s:name>Evington Medical Centre</s:name>
        <s:odsCode>C82088</s:odsCode>
        <s:address>
          <s:addressLine>2 - 6 Halsbury Street</s:addressLine>
          <s:addressLine>Leicester</s:addressLine>
          <s:addressLine>Leicestershire</s:addressLine>
          <s:postcode>LE2 1QA</s:postcode>
        </s:address>
        <s:contact type="General">
          <s:telephone>0116 3190343</s:telephone>
        </s:contact>
        <s:geographicCoordinates>
          <s:longitude>-1.10676002502441</s:longitude>
          <s:latitude>52.624267578125</s:latitude>
        </s:geographicCoordinates>
        <s:Distance>0.834829502560211</s:Distance>
      </s:organisationSummary>
    </content>
  </entry>
</feed>

这是我期待的输出:

{
   "success":true,
   "data":{
      "13":{
         "name":"Highfields Surgery (R Wadhwa)",
         "odscode":"C82116",
         "addressline0":"25 Severn Street",
         "addressline1":"Leicester",
         "addressline2":"Leicestershire",
         "postcode":"LE2 0NN",
         "telephone":"01162543253",
         "longitude":"-1.11859357357025",
         "latitude":"52.6293983459473",
         "distance":"0.247038430918239"
      },
      "14":{
         "name":"Dr R Kapur & Partners",
         "odscode":"C82659",
         "addressline0":"St Peters Health Centre",
         "addressline1":"Sparkenhoe Street",
         "addressline2":"Leicester",
         "addressline3":"Leicestershire",
         "postcode":"LE2 0TA",
         "telephone":"01162951258",
         "longitude":"-1.11907768249512",
         "latitude":"52.6310386657715",
         "distance":"0.30219913005026"
      },
      "15":{
         "name":"Shefa Medical Practice",
         "odscode":"C82080",
         "addressline0":"St Peters Health Centre",
         "addressline1":"Sparkenhoe Street",
         "addressline2":"Leicester",
         "addressline3":"Leicestershire",
         "postcode":"LE2 0TA",
         "telephone":"01162957835",
         "longitude":"-1.11907768249512",
         "latitude":"52.6310386657715",
         "distance":"0.30219913005026"
      },
      "16":{
         "name":"St Peter's Health Centre - Mansingh & Partner",
         "odscode":"C82660",
         "addressline0":"Sparkenhoe Street",
         "addressline1":"Leicester",
         "addressline2":"Leicestershire",
         "postcode":"LE2 0TA",
         "telephone":"01162957827",
         "longitude":"-1.11907768249512",
         "latitude":"52.6310386657715",
         "distance":"0.30219913005026"
      },
      "17":{
         "name":"Al-Waqas Medical Centre",
         "odscode":"C82099",
         "addressline0":"AL-Waqas Medical Practice",
         "addressline1":"91 St Peters Road",
         "addressline2":"Leicester",
         "addressline3":"Leicestershire",
         "postcode":"LE2 1DJ",
         "telephone":"01162543003",
         "longitude":"-1.10840618610382",
         "latitude":"52.6290435791016",
         "distance":"0.458084198394662"
      },
      "18":{
         "name":"Community Health Centre",
         "odscode":"C82643",
         "addressline0":"Melbourne Centre",
         "addressline1":"Melbourne Road",
         "addressline2":"Leicester",
         "addressline3":"Leicestershire",
         "postcode":"LE2 0GU",
         "telephone":"01162622946",
         "longitude":"-1.11336529254913",
         "latitude":"52.6338653564453",
         "distance":"0.462480666213577"
      },
      "19":{
         "name":"Sayeed Medical Centre",
         "odscode":"C82060",
         "addressline0":"352-354 East Park Road",
         "addressline1":"Leicester",
         "addressline2":"Leicestershire",
         "postcode":"LE5 5AY",
         "telephone":"01163232030",
         "longitude":"-1.10658276081085",
         "latitude":"52.630802154541",
         "distance":"0.581034496166074"
      },
      "20":{
         "name":"Melbourne Street Surgery",
         "odscode":"C82031",
         "addressline0":"56 Melbourne Street",
         "addressline1":"Leicester",
         "addressline2":"Leicestershire",
         "postcode":"LE2 0AS",
         "telephone":"01162536299",
         "longitude":"-1.11437559127808",
         "latitude":"52.636344909668",
         "distance":"0.717122615984056"
      },
      "21":{
         "name":"East Park Medical Centre - R P Pandya",
         "odscode":"C82037",
         "addressline0":"264-266 East Park Road",
         "addressline1":"Leicester",
         "addressline2":"Leicestershire",
         "postcode":"LE5 5FD",
         "telephone":"01162736330",
         "longitude":"-1.10444343090057",
         "latitude":"52.633544921875",
         "distance":"0.822717143851754"
      },
      "22":{
         "name":"Evington Medical Centre",
         "odscode":"C82088",
         "addressline0":"2 - 6 Halsbury Street",
         "addressline1":"Leicester",
         "addressline2":"Leicestershire",
         "postcode":"LE2 1QA",
         "telephone":"0116 3190343",
         "longitude":"-1.10676002502441",
         "latitude":"52.624267578125",
         "distance":"0.834829502560211"
      }
   }
}

【问题讨论】:

  • 使用不同的 XML 解析器可能会更好。我写了这个,人们似乎很喜欢:github.com/sabre-io/xml
  • @Evert 谢谢,我去看看

标签: php json xml foreach


【解决方案1】:

您需要使用适当的方法来遍历 XML 文档,而不是查看每个元素并检查其名称。

您的两个最佳选择是 DOM 方法和 XPath。如果您使用过前端 JavaScript 代码(例如 document.getElementsByTagNamedocument.getElementById),您会熟悉前者。后者的学习曲线更陡峭,但功能更强大。 (XSLT 也是转换 XML 的一个不错的选择,但我对它不是很熟悉。)

不过,第一步是使用适当的 XML 库。您使用的 XML 函数是 very 低级的。我建议改用 PHP 的 DomDocument 扩展名。让我们潜入!

<?php
$xml = file_get_contents("nhs.xml");
// assume XML document is stored in a variable called $xml
$dom = new DomDocument;
$dom->loadXml($xml);
// thankfully we can ignore namespaces!
$summaries = $dom->getElementsByTagName("organisationSummary");
// go through each <organisationSummary> element
foreach ($summaries as $os) {
    $entry_data = [
        // note we're using $os and not $dom now, so we get child elements of this particular element
        "name"         => $os->getElementsByTagName("name")[0]->textContent,
        "odscode"      => $os->getElementsByTagName("odsCode")[0]->textContent,
        "addressline0" => $os->getElementsByTagName("addressLine")[0]->textContent,
        // provide a default empty string in case there's no further lines
        "addressline1" => $os->getElementsByTagName("addressLine")[1]->textContent ?? "",
        "addressline2" => $os->getElementsByTagName("addressLine")[2]->textContent ?? "",
        "addressline3" => $os->getElementsByTagName("addressLine")[3]->textContent ?? "",
        "postcode"     => $os->getElementsByTagName("postcode")[0]->textContent,
        "telephone"    => $os->getElementsByTagName("telephone")[0]->textContent,
        "longitude"    => $os->getElementsByTagName("longitude")[0]->textContent,
        "latitude"     => $os->getElementsByTagName("latitude")[0]->textContent,
        "distance"     => $os->getElementsByTagName("Distance")[0]->textContent,
    ];
    $json_data[] = $entry_data;
}
if (count($json_data)) {
    $output = ["success" => true, "data" => $json_data];
} else {
    $output = ["success" => false];
}
echo json_encode($output, JSON_PRETTY_PRINT);

【讨论】:

    【解决方案2】:

    您可以使用 DOM 和 XPath 表达式。所有数据都在{https://api.nhs.uk/data/services}organisationSummary 节点内。

    以下示例为命名空间 https://api.nhs.uk/data/services 注册前缀 service(这就是您示例中的 s 解析的内容)。然后它使用//service:organisationSummary 表达式获取任何{https://api.nhs.uk/data/services}organisationSummary 节点。

    对于每个组织,它使用标量值的表达式构建一个$item 变量。 {https://api.nhs.uk/data/services}addressLine 节点使用循环。

    // create the DOM document and load the XML 
    $document = new DOMDocument();
    $document->loadXML($xml);
    // create an Xpath instance for the document - register namespace
    $xpath = new DOMXpath($document);
    $xpath->registerNamespace('service', 'https://api.nhs.uk/data/services');
    $json = [
      "success" => true,
      // force object for data - it will be an array otherwise
      "data" => new stdClass()
    ];
    
    // iterate over all organisationSummary nodes
    foreach ($xpath->evaluate('//service:organisationSummary') as $index => $organisation) {
      // fetch single values
      $item = [
        "name" => $xpath->evaluate('string(service:name)', $organisation),
        "odscode" => $xpath->evaluate('string(service:odsCode)', $organisation),
        "postcode" => $xpath->evaluate('string(service:address/service:postcode)', $organisation),
        "telephone" => $xpath->evaluate('string(service:contact/service:telephone)', $organisation),
        "longitude" => $xpath->evaluate('string(service:geographicCoordinates/service:longitude)', $organisation),
        "latitude" => $xpath->evaluate('string(service:geographicCoordinates/service:latitude)', $organisation),
        "distance" => $xpath->evaluate('string(service:Distance)', $organisation)
      ];
      // add the addressLine values
      foreach ($xpath->evaluate('service:address/service:addressLine', $organisation) as $lineIndex => $line) {
        $item['addressline'.$lineIndex] = $line->textContent;
      }
      // add the $item
      $json['data']->{$index} = $item;
    }
    
    echo json_encode($json, JSON_PRETTY_PRINT);
    

    输出:

    {
        "success": true,
        "data": {
            "0": {
                "name": "Highfields Surgery (R Wadhwa)",
                "odscode": "C82116",
                "postcode": "LE2 0NN",
                "telephone": "01162543253",
                "longitude": "-1.11859357357025",
                "latitude": "52.6293983459473",
                "distance": "0.247038430918239",
                "addressline0": "25 Severn Street",
                "addressline1": "Leicester",
                "addressline2": "Leicestershire"
            },
            "1": {
                "name": "Dr R Kapur & Partners",
                "odscode": "C82659",
                "postcode": "LE2 0TA",
                "telephone": "01162951258",
                "longitude": "-1.11907768249512",
                "latitude": "52.6310386657715",
                "distance": "0.30219913005026",
                "addressline0": "St Peters Health Centre",
                "addressline1": "Sparkenhoe Street",
                "addressline2": "Leicester",
                "addressline3": "Leicestershire"
            },
            ...
    

    【讨论】:

    • 非常感谢,我会在 xpath 上做更多的阅读,因为我还没有真正尝试过
    猜你喜欢
    • 1970-01-01
    • 2019-07-21
    • 2017-05-20
    • 1970-01-01
    • 2023-03-17
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    相关资源
    最近更新 更多