我必须处理大约 750 个 xml 文件才能产生融洽的关系。我可能应该使用 XSLT 或使用 XPath,但现在可能为时已晚。
所以我的问题;对于前几张唱片,一切正常。似乎有几个 XML 文件没有我正在调用的节点。我试过使用 isset!== null ,这不起作用,只是给了我同样的错误。即



使用以下可能是错误的,对吧?

 if($xml_entry->children('http://www.isotc211.org/2005/gmd')->identificationInfo->MD_DataIdentification->citation->CI_Citation->title->children('http://www.isotc211.org/2005/gco'))

我试图解析的 XML 文件的一个小样本是(整个 xml 可以在 here 中找到:
 <gmd:contact>
    <gmd:CI_ResponsibleParty>
      <gmd:individualName>
        <gco:CharacterString>B. Boers</gco:CharacterString>
      </gmd:individualName>
      <gmd:organisationName>
        <gco:CharacterString>Staatsbosbeheer</gco:CharacterString>
      </gmd:organisationName>
      <gmd:positionName>
        <gco:CharacterString>Contactpersoon</gco:CharacterString>
      </gmd:positionName>
    </gmd:CI_ResponsibleParty>
</gmd:contact>

还有我的 PHP:
<?php
        $xml_url = "http://www.nationaalgeoregister.nl/geonetwork/srv/dut/q?fast=index&from=1&to=10000&geometry=POLYGON((5.5963%2053.3162%2C5.5963%2053.5766%2C6.9612%2053.5766%2C6.9612%2053.3162%2C5.5963%2053.3162))";
        $xml_single_url = "http://www.nationaalgeoregister.nl/geonetwork/srv/dut/xml.metadata.get?uuid=";
        //Load the XML
        $xml = simplexml_load_file($xml_url);
        $xml_array = array();

        //Loop through all the nodes with 'metadata' and put uuid in the array
        foreach($xml->metadata as $metadata) {
                $xml_array[] = $metadata->children('http://www.fao.org/geonetwork')->children()->uuid;
        }
        echo "<table>"
        ."<tr>"
        ."<td>Title</td>"
        ."<td>Owner</td>"
        ."<td>Purpose</td>"
        ."<td>Tags</td>"
        ."<td>Url</td>"
        ."<td>Url</td>"
        ."</tr>";

        $i = 0;
        //For every id in the $xml_array
        foreach($xml_array as $ar)
        {
            //Just a limit for testing purposes
            $i++;
            if($i == 100)
            {
                break;
            }
            //Loads the xml file
            $xml_entry = simplexml_load_file($xml_single_url .$ar);
            echo "<tr>";

            //Title
            echo "<td>"
            .$xml_entry->children('http://www.isotc211.org/2005/gmd')->identificationInfo->MD_DataIdentification->citation->CI_Citation->title->children('http://www.isotc211.org/2005/gco')->CharacterString
            ."</td>";

            //Owner
            echo "<td>"
            .$xml_entry->children('http://www.isotc211.org/2005/gmd')->contact->CI_ResponsibleParty->organisationName->children('http://www.isotc211.org/2005/gco')->CharacterString
            ."</td>";

            //Purpose
            echo "<td>"
            .$xml_entry->children('http://www.isotc211.org/2005/gmd')->identificationInfo->MD_DataIdentification->purpose->children('http://www.isotc211.org/2005/gco')->CharacterString
            ."</td>";

            //Tags
            //Transfer
            echo "</tr>";
        }
        echo "</table>";

?>

我试图自己找到解决方案,但似乎无法找到它..

最佳答案

这些行的问题:



是它们太长而且太容易出错。即使是 SimpleXML 也允许这种“简单”的访问,如果它在某处找不到元素,它将返回 NULL,然后您会收到警告甚至致命错误。

对于您的用例,使用 xpath 查询来完成这项工作要好得多。由于您需要访问表示元数据的多个属性,因此我建议首先将其包装到它自己的一个类中,例如 SimpleXMLElementXpathObject ,其中使用的 PropertyIterator can be found here

这种类型允许您使用 SimpleXMLElement 和通过将属性映射到 xpath 查询来描述属性的数组来定义要查找的元数据:

$metaDef = array(
    'title'   => 'gmd:identificationInfo//gmd:CI_Citation/gmd:title/gco:CharacterString',
    'owner'   => 'gmd:contact/gmd:CI_ResponsibleParty/gmd:organisationName/gco:CharacterString',
    'purpose' => 'gmd:identificationInfo/gmd:MD_DataIdentification/gmd:purpose/gco:CharacterString',
);

如您所见,每个键都有一个 xpath 表达式。键将变成属性。然后,这允许您即时进行映射,例如:
$meta = new SimpleXMLElementXpathObject($xml, $metaDef);
echo $meta->title, "\n";
echo json_encode($meta, JSON_PRETTY_PRINT), "\n";

输出:
Natuur - Ecologische verbindingszones
{
    "title": "Natuur - Ecologische verbindingszones",
    "owner": "provincie Frysl\u00e2n",
    "purpose": "Beleidsnota \"ecologische verbindingszones in Frysl\u00e2n\" vastgesteld door Provinciale Staten op 4 oktober 2006. Opgenomen in het Streekplan 2007"
}

如果 xpath 没有返回结果,则给出 NULL。这意味着属性是可选的,您不会看到任何警告甚至致命错误。澄清一下:这基本上是使用 SimpleXMLElement 中的 xpath 方法,因此您也可以自己运行这些查询。

一个更完整的例子:
$query = new GeoNetwork_Query();
$query
    ->setGeometry('POLYGON((5.5963 53.3162,5.5963 53.5766,6.9612 53.5766,6.9612 53.3162,5.5963 53.3162))')
    ->setLimit(10);

$metaObj = function (GeoNetwork_Resource $resource) {
    $metaDef = array(
        'title'   => 'gmd:identificationInfo//gmd:CI_Citation/gmd:title/gco:CharacterString',
        'owner'   => 'gmd:contact/gmd:CI_ResponsibleParty/gmd:organisationName/gco:CharacterString',
        'purpose' => 'gmd:identificationInfo/gmd:MD_DataIdentification/gmd:purpose/gco:CharacterString',
    );

    return new SimpleXMLElementXpathObject($resource->getIterator(), $metaDef);
};

$resources = new GeoNetwork_UuidIterator($query);
$objects   = new DecoratingIterator($resources, $metaObj);
$table     = new HtmlTableIterator($objects, ['Title', 'Owner', 'Purpose']);

echo "<table>\n";
foreach ($table as $row) {
    echo $row, "\n";
}
echo "</table>\n";

我将输出限制为 10,这样它就不会创建太长的列表(对于查询结果)。您还可以通过将 $objects 包装在 LimitIterator 中来限制 ojit_code。上面代码的示例输出:
<table>
<tr><td>Title</td><td>Owner</td><td>Purpose</td></tr>
<tr><td>Natuur - Ecologische verbindingszones</td><td>provincie Fryslân</td><td>Beleidsnota "ecologische verbindingszones in Fryslân" vastgesteld door Provinciale Staten op 4 oktober 2006. Opgenomen in het Streekplan 2007</td></tr>
<tr><td>CORINE: Veranderingen in landgebruik in Nederland tussen 1986 en 2000.</td><td>Alterra, Wageningen UR</td><td>Het monitoren van landgebruiksveranderingen op Europese schaal volgens een standaard methode.</td></tr>
<tr><td>Viswaterkaart Sportvisserij</td><td>Sportvisserij Nederland</td><td>Elke sportvisser moet exact weten waar die onder welke (bijz.) voorwaarden mag hengelen.</td></tr>
<tr><td>Veiligheidsafstand vuurwerk</td><td>Interprovinciaal Overleg</td><td>Risicokaart</td></tr>
<tr><td>Weggeg convergenties</td><td>Rijkswaterstaat Data en ICT Dienst (RWS DID)</td><td>Ruimtelijke analyses waarbij ligging van infrastructuur van belang is en bereikbaarheidsberekeningen</td></tr>
<tr><td>Beheerkaart Nat Versie januari 2008</td><td>Rijkswaterstaat Data en ICT Dienst (RWS DID)</td><td>De Beheerkaart Nat wordt door de natte districten van Rijkswaterstaat gebruikt ten behoeve van beheer en onderhoud van zijn beheerobjecten van de watersystemenen. Het NIS gebruikt de gegevens om ondermeer de benodigde budgetten te bepalen voor beheer en onderhoud.</td></tr>
<tr><td>Orthofotomozaieken_project</td><td>Rijkswaterstaat Data en ICT Dienst (RWS DID)</td><td>Gebruik als ondergrond</td></tr>
<tr><td>Knelpunten in LAW-routes</td><td>Stichting Wandelnet</td><td>Inventarisatie van knelpunten in LAW-routes voor provincies</td></tr>
<tr><td>Electronische zeekaarten Ned. Cont. Plat usage Harbour</td><td>Dienst der Hydrografie</td><td>Veilige navigatie</td></tr>
<tr><td>Maatregelzone kernenergie</td><td>Interprovinciaal Overleg</td><td>Risicokaart</td></tr>
</table>

在上面的代码中,我使用了这里的类:https://gist.github.com/hakre/94a36e4587214a6e9bc9

关于PHP simpleXML如何检查嵌套子项是否存在,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16802554/

10-15 13:53
查看更多