simplexml_load_string无法解析我的XML字符串。字符集问题?

3
我正在使用以下PHP代码从NOAA潮汐报告站API读取XML数据:
$rawxml = file_get_contents(
    "http://opendap.co-ops.nos.noaa.gov/axis/webservices/activestations/"
    ."response.jsp?v=2&format=xml&Submit=Submit"
);
$rawxml = utf8_encode($rawxml);
$ob = simplexml_load_string($rawxml);
var_dump($ob);

不幸的是,我最终得到了以下内容:

object(SimpleXMLElement)#246 (0) { }

在我看来,XML格式完全正确 - 为什么它不能解析?从查看另一个问题(Simplexml_load_string() fail to parse error)中,我得出的想法是头部可能是问题所在——http调用确实返回了"ISO-8859-1"字符集值。但加入 utf8_encode() 的调用似乎行不通。

特别令人困惑的是,simplexml_load_string() 实际上并没有失败——它返回了一串愉快的XML数组,只是里面没有任何内容!


看起来有很多标签没有正确地终止。使用 http://www.xmlvalidation.com/ 进行了检查,得到了 The element type "shef_id" must be terminated by the matching end-tag "</shef_id>" 的错误提示。 - Sergiu Paraschiv
你是否检查 SimpleXML 记录或报告的错误?为了获得最大输出,请尝试以下方法:error_reporting(E_ALL); ini_set('display_errors',true);libxml_use_internal_errors(false); - IMSoP
1个回答

4
你被SimpleXML书中最古老的把戏愚弄了(我也被愚弄了):SimpleXML没有将整个文档解析为PHP对象,而是提供了一个PHP API来访问内部结构。像var_dump这样的函数无法看到此结构,因此不能始终给出有关对象内容的有用信息。
它看起来“空”的原因是它列出了根元素的子元素,这些子元素位于默认命名空间中 - 但实际上没有任何子元素位于其中,“soapenv:”命名空间中才包含所有子元素。
要访问命名空间元素,您需要使用children()方法,传入完整的命名空间名称(建议)或其本地前缀(更简单,但可能会因文件生成方式在另一端发生变化而出现问题)。要切换回“默认命名空间”,请使用->children(null)
因此,您可以像这样获取第一个stationV2元素的ID属性(演示):
// Define constant for the namespace names, rather than relying on the prefix the remote service uses remaining stable
define('NS_SOAP', 'http://schemas.xmlsoap.org/soap/envelope/');

// Download the XML
$rawxml = file_get_contents("http://opendap.co-ops.nos.noaa.gov/axis/webservices/activestations/response.jsp?v=2&format=xml&Submit=Submit");
// Parse it
$ob = simplexml_load_string($rawxml);

// Use it!
echo $ob->children(NS_SOAP)->Body->children(null)->ActiveStationsV2->stationsV2->stationV2[0]['ID'];

我已经写了一些和SimpleXML一起使用的调试函数,它们应该比var_dump等函数更少误导性。这里有一个实时演示,展示了你的代码和simplexml_dump函数


哇。非常感谢。现在运行得非常好。这太棒了——你可能猜到了,我完全卡住了。 - Chris Rae

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接