PHP使用XMLReader获取XML标签值并按营业时间生成新标签咨询
核心问题解决思路
<opening_times>标签内存储的是标准JSON字符串,直接通过json_decode()即可提取所有营业时段、时区数据- 你当前的XMLReader遍历逻辑已经可以获取单个offer节点的所有数据,只要在遍历循环内单独处理每个offer即可
- 原有时间比对函数存在2个问题:
- 用了12小时制的
date('h:i'),应该用24小时制的date('H:i')避免上下午判断错误 - 没有适配
<opening_times>里标注的时区,会导致时间判断偏差
- 用了12小时制的
完整实现代码
<?php // 时间校验函数:传入解析后的opening_times数组,返回是否在营业时间内 function is_opening($opening_times_data) { // 先设置对应时区 $timezone = new DateTimeZone($opening_times_data['timezone'] ?? 'Europe/Warsaw'); $now = new DateTime('now', $timezone); // 获取当前周几(1=周一 到 7=周日,和JSON里的键对应) $current_day = $now->format('N'); $current_time = $now->format('H:i'); // 当天没有营业时段直接返回false if (empty($opening_times_data[$current_day])) { return false; } // 遍历当天所有营业时段判断 foreach ($opening_times_data[$current_day] as $time_slot) { $opening = $time_slot['opening']; $closing = $time_slot['closing']; // H:i格式的时间字符串字典序和时间序一致,直接比较即可 if ($current_time >= $opening && $current_time <= $closing) { return true; } } return false; } // 初始化XML读写 $reader = new XMLReader(); $reader->open('feed_sample.xml'); // 用DOMDocument生成新XML,保证CDATA格式正确 $new_xml = new DOMDocument('1.0', 'UTF-8'); $new_xml->formatOutput = true; $offers_root = $new_xml->createElement('offers'); $new_xml->appendChild($offers_root); // 遍历原XML的每个offer节点 while ($reader->read()) { if ($reader->name === 'offer' && $reader->nodeType == XMLReader::ELEMENT) { // 把单个offer节点转成DOMElement方便操作 $offer_dom = dom_import_simplexml(simplexml_load_string($reader->readOuterXml())); // 导入到新XML文档 $offer_node = $new_xml->importNode($offer_dom, true); // 提取opening_times的JSON内容解析 $opening_times_str = $offer_node->getElementsByTagName('opening_times')->item(0)->nodeValue; $opening_times_data = json_decode($opening_times_str, true); // 计算is_active值 $is_active = is_opening($opening_times_data) ? 'true' : 'false'; // 创建带CDATA的is_active节点 $is_active_node = $new_xml->createElement('is_active'); $cdata = $new_xml->createCDATASection($is_active); $is_active_node->appendChild($cdata); // 把节点添加到offer下 $offer_node->appendChild($is_active_node); // 把处理好的offer添加到新XML根节点 $offers_root->appendChild($offer_node); } } $reader->close(); // 输出新XML文件 $new_xml->save('new_feed.xml'); ?>
代码说明
- 遍历原XML时每次循环内处理的就是单个offer节点,直接单独提取对应opening_times的值即可
- 用DOMDocument生成新XML保证CDATA标签格式正确,不会出现转义错误
- 时间判断用PHP的DateTime类适配指定时区,避免系统时区不同导致的判断错误
内容的提问来源于stack exchange,提问作者Kacper Woźniak
相关产品推荐
相关产品推荐

