【问题标题】:simpleXML in PHP reading elements from nested namespaces in XML documentPHP 中的 simpleXML 从 XML 文档中的嵌套命名空间读取元素
【发布时间】:2012-05-11 05:46:19
【问题描述】:

我被难住了。我在一个文件中有以下 XML:

<?xml version="1.0" encoding="UTF-8"?>
<grant:GrantApplication xmlns:grant="http://apply.grants.gov/system/MetaGrantApplication" xmlns:globLib="http://apply.grants.gov/system/GlobalLibrary-V1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://apply.grants.gov/system/MetaGrantApplication http://apply07.grants.gov/apply/opportunities/schemas/agency/oppEPA-R5-GL2011-1-cfda66.469.xsd">
    <grant:Forms>
        <EPA_KeyContacts:KeyContactPersons xmlns:EPA_KeyContacts="http://apply.grants.gov/forms/EPA_KeyContacts-V1.1" EPA_KeyContacts:FormVersion="1.1">
            <EPA_KeyContacts:AuthorizedRepresentative>
                <globLib:Name xmlns:globLib="http://apply.grants.gov/system/GlobalLibrary-V2.0">
                    <globLib:FirstName>Jane</globLib:FirstName>
                    <globLib:LastName>Doe</globLib:LastName>
                </globLib:Name>
            </EPA_KeyContacts:AuthorizedRepresentative>
        </EPA_KeyContacts:KeyContactPersons>
        <EPA4700_4_2_0:EPA4700_4_2_0 xmlns:EPA4700_4_2_0="http://apply.grants.gov/forms/EPA4700_4_2_0-V2.0" EPA4700_4_2_0:FormVersion="2.0">
            <EPA4700_4_2_0:ApplicantInfo>
                <EPA4700_4_2_0:ApplicantName>ABC 123</EPA4700_4_2_0:ApplicantName>
                <EPA4700_4_2_0:ApplicantAddress>
                    <EPA4700_4_2_0:Address>123 Street</EPA4700_4_2_0:Address>
                    <EPA4700_4_2_0:City>Buffalo</EPA4700_4_2_0:City>
                    <EPA4700_4_2_0:State>NY: New York</EPA4700_4_2_0:State>
                    <EPA4700_4_2_0:ZipCode>12345</EPA4700_4_2_0:ZipCode>
                </EPA4700_4_2_0:ApplicantAddress>
            <EPA4700_4_2_0:ApplicantInfo>
        <EPA4700_4_2_0:EPA4700_4_2_0 xmlns:EPA4700_4_2_0="http://apply.grants.gov/forms/EPA4700_4_2_0-V2.0" EPA4700_4_2_0:FormVersion="2.0">
        <SF424_2_1:SF424_2_1 xmlns:SF424_2_1="http://apply.grants.gov/forms/SF424_2_1-V2.1" SF424_2_1:FormVersion="2.1">
            <SF424_2_1:ContactPerson>
                <globLib:FirstName xmlns:globLib="http://apply.grants.gov/system/GlobalLibrary-V2.0">Jane</globLib:FirstName>
                <globLib:LastName xmlns:globLib="http://apply.grants.gov/system/GlobalLibrary-V2.0">Doe</globLib:LastName>
            <SF424_2_1:ContactPerson>
        <SF424_2_1:SF424_2_1>
    </grant:Forms>
</grant:GrantApplication>

在 PHP 中使用 SimpleXML,我有以下代码:

$xml = simplexml_load_file($appdir);

$xml->registerXPathNamespace("grant","http://apply.grants.gov/system/MetaGrantApplication");
$xml->registerXPathNamespace("header","http://apply.grants.gov/system/Header-V1.0");
$xml->registerXPathNamespace("globLib","http://apply.grants.gov/system/GlobalLibrary-V2.0");
$xml->registerXPathNamespace("EPA_KeyContacts","http://apply.grants.gov/forms/EPA_KeyContacts-V1.1");
$xml->registerXPathNamespace("SF424A","http://apply.grants.gov/forms/SF424A-V1.0");
$xml->registerXPathNamespace("SF424_2_1","http://apply.grants.gov/forms/SF424_2_1-V2.1");
$xml->registerXPathNamespace("EPA4700_4_2_0","http://apply.grants.gov/forms/EPA4700_4_2_0-V2.0");

$rawContactFirstName = $xml->xpath("/grant:GrantApplication/grant:Forms/SF424_2_1:SF424_2_1/SF424_2_1:ContactPerson/globLib:FirstName");
$contactFirstName = $rawContactFirstName[0];

$rawContactLastName = $xml->xpath("/grant:GrantApplication/grant:Forms/EPA_KeyContacts:KeyContactPersons/EPA_KeyContacts:AuthorizedRepresentative/globLib:Name/globLib:LastName");
$contactLastName = $rawContactLastName[0];

$rawStreetAddress = $xml->xpath("/grant:GrantApplication/grant:Forms/EPA4700_4_2_0:EPA4700_4_2_0/EPA4700_4_2_0:ApplicantInfo/EPA4700_4_2_0:ApplicantAddress/EPA4700_4_2_0:Address");
$streetAddress = $rawStreetAddress[0];

$rawCity = $xml->xpath("/grant:GrantApplication/grant:Forms/EPA4700_4_2_0:EPA4700_4_2_0/EPA4700_4_2_0:ApplicantInfo/EPA4700_4_2_0:ApplicantAddress/EPA4700_4_2_0:City");
$city = $rawCity[0];

$rawState = $xml->xpath("/grant:GrantApplication/grant:Forms/EPA4700_4_2_0:EPA4700_4_2_0/EPA4700_4_2_0:ApplicantInfo/EPA4700_4_2_0:ApplicantAddress/EPA4700_4_2_0:State");
$state = $rawState[0];

$rawZip = $xml->xpath("/grant:GrantApplication/grant:Forms/EPA4700_4_2_0:EPA4700_4_2_0/EPA4700_4_2_0:ApplicantInfo/EPA4700_4_2_0:ApplicantAddress/EPA4700_4_2_0:ZipCode");
$zip = $rawZip[0];

echo $contactFirstName."<br>".
     $contactLastName."<br>".
     $streetAddress."<br>".
     $city."<br>".
     $state."<br>".
     $zip."<br>";

我得到以下输出:

注意:未定义的偏移量:file.php 第 105 行中的 0 注意:未定义 偏移量:第 108 行 file.php 中的 0

123 街

布法罗

纽约:纽约

12345

第 105 行引用 $rawContactFirstName[0] 和第 108 行引用 $rawContactLastName[0]

名字和姓氏在文档中出现了两次,由于引用 globLib 命名空间的方式不同,我从第一次出现引用姓氏,从第二次出现引用名字。

我无法使用 globLib 命名空间从任何元素中获取任何信息,我不明白为什么。只要不使用 globLib 命名空间,我就可以从文档中获取任何其他信息。

$xml->xpath();应该返回一个数组。考虑以下几点:

print_r($rawContactFirstName);

输出: 数组( )

var_dump($rawContactFirstName);
var_dump($rawContactFirstName[0]);

输出: 数组(0) { }

我不明白所有其他命名空间如何能够毫无问题地返回数据,除了这个使用完全相同的技术。根据http://validator.w3.org/,XML 文档是有效的。

有什么想法吗?

【问题讨论】:

    标签: php xml namespaces simplexml


    【解决方案1】:

    尝试更改此行:

    $xml->registerXPathNamespace("globLib","http://apply.grants.gov/system/GlobalLibrary-V2.0");
    

    到:

    $xml->registerXPathNamespace("globLib2","http://apply.grants.gov/system/GlobalLibrary-V2.0");
    

    (或您想使用的任何唯一前缀)。

    然后在你的 xpath 中引用它:

    $rawContactFirstName = $xml->xpath("/grant:GrantApplication/grant:Forms/SF424_2_1:SF424_2_1/SF424_2_1:ContactPerson/globLib2:FirstName");
    

    我认为发生的事情是前缀“globLib”已经在文档元素中使用不同的 URI 注册,这在某种程度上使registerXPathNamespace 感到困惑。

    附带说明,您发布的 XML 似乎无效。它有一堆未封闭的标签和用开放标签“封闭”的标签 - 所以我还要确保你使用的任何 XML 有效的。

    【讨论】:

    • 嘿 Ryan,在发布这个问题后不久,我更改了前缀。 globLib 前缀已注册并导致冲突。感谢您的回答,对于延误,我深表歉意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-21
    • 2019-02-17
    相关资源
    最近更新 更多