PHP解析Atom XML订阅源时如何提取每个条目中最后一个subject标签的值
PHP解析Atom XML订阅源时如何提取每个条目中最后一个subject标签的值
嘿,我最近在帮一个电子书出版商做PHP解析Atom XML订阅源的活儿,大部分功能都搞定了,但卡在一个小问题上——怎么提取每个条目里最后一个<subject>标签的值?这个最后一个标签是出版商自己的分类标签,前面的都是国会图书馆主题标题(LCSH),而且每个条目里的<subject>数量还不固定,真有点头疼!
先给大家看看我手头的示例XML片段(简化后,包含三本图书的条目):
<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <entry> <title>Book 1: Example Title</title> <subject>Library of Congress Subject 1</subject> <subject>Library of Congress Subject 2</subject> <subject>Publisher's Category A</subject> </entry> <entry> <title>Book 2: Another Title</title> <subject>Library of Congress Subject X</subject> <subject>Publisher's Category B</subject> </entry> <entry> <title>Book 3: Third Title</title> <subject>Publisher's Category C</subject> </entry> </feed>
我之前尝试用SimpleXML来解析,但一直没找到靠谱的方式拿到最后一个<subject>,后来摸索出两种可行的方法,分享给大家:
方法1:利用SimpleXML的数组特性
SimpleXML会把同名的子元素处理成数组形式,所以我们可以先获取当前条目下所有的<subject>,再通过数组索引拿到最后一个:
// 加载Atom订阅源文件(也可以用字符串加载) $xml = simplexml_load_file('your-feed-path.xml'); if ($xml === false) { die('加载XML失败,请检查文件路径或格式'); } // 遍历每个图书条目 foreach ($xml->entry as $entry) { // 获取当前条目下所有subject元素 $subjectElements = $entry->subject; // 先判断是否有subject元素,避免空数组报错 if (count($subjectElements) > 0) { // 取最后一个元素,转成字符串(否则是SimpleXMLElement对象) $lastSubject = (string)$subjectElements[count($subjectElements) - 1]; echo "《{$entry->title}》的出版商分类:{$lastSubject}\n"; } else { echo "《{$entry->title}》没有分类标签\n"; } }
方法2:用XPath直接定位最后一个元素
XPath有个last()函数,可以直接选中节点集中的最后一个元素,用这个方法更简洁,不用手动计算索引:
$xml = simplexml_load_file('your-feed-path.xml'); if ($xml === false) { die('加载XML失败,请检查文件路径或格式'); } // 注意:如果Atom feed带命名空间(大部分都带),需要先注册命名空间 $xml->registerXPathNamespace('atom', 'http://www.w3.org/2005/Atom'); // 用XPath遍历所有entry节点 $entries = $xml->xpath('//atom:entry'); foreach ($entries as $entry) { // 用XPath直接获取当前entry下的最后一个subject $lastSubjectNodes = $entry->xpath('atom:subject[last()]'); if (!empty($lastSubjectNodes)) { $lastSubject = (string)$lastSubjectNodes[0]; echo "《{$entry->title}》的出版商分类:{$lastSubject}\n"; } else { echo "《{$entry->title}》没有分类标签\n"; } }
小提醒
如果你的Atom feed使用了自定义命名空间,记得先通过registerXPathNamespace()注册对应的命名空间前缀,否则XPath会找不到节点哦。
备注:内容来源于stack exchange,提问作者Dɑvíd
相关产品推荐
相关产品推荐

