如何在 XMLReader 中获取标记名称的值 + 如何使用该值进行进一步分析

Posted

技术标签:

【中文标题】如何在 XMLReader 中获取标记名称的值 + 如何使用该值进行进一步分析【英文标题】:How get value of Tag Name in XMLReader + how use that value for further analysis 【发布时间】:2021-11-19 14:42:00 【问题描述】:

我有这样的 XML 文件来解析(短版)。 我需要创建包含附加标签的新 XML 文件:<is_active><![CDATA[true]></is_active>. 有一个简单的条件,<is_active> 为 TRUE,当: - 当前时间(当我们启动我们的代码时)在 标签中给出的小时之间(我们也检查天); - 否则 <is_active> 为 FALSE。

<?xml version="1.0" encoding="UTF-8" ?>
<offers>
<offer>
    <id><![CDATA[2109]]></id>
    <name><![CDATA[Sleek Frozen Sausages]]></name>
    <category><![CDATA[Sleek]]></category>
    <description><![CDATA[Eum aut qui est delectus suscipit aut voluptas quaerat maiores architecto perferendis dolorum tenetur iure nemo omnis laboriosam voluptatem et iste molestias sed voluptas eum facilis aliquam tempora autem aspernatur ipsum corrupti cum corrupti quae dolor modi consequatur provident illo maiores eius aspernatur id nostrum nisi repellat enim a hic unde laboriosam possimus est ipsam qui mollitia nesciunt est culpa voluptatem sit dignissimos quidem facilis dolorem facilis et explicabo ea veniam quis architecto autem occaecati quaerat omnis reprehenderit doloribus labore saepe asperiores a ea possimus dolor necessitatibus numquam doloremque velit fuga ipsam numquam quia omnis voluptas voluptas rerum sint eveniet sit in error quia nemo delectus perferendis asperiores quam quam assumenda reiciendis sunt aut et saepe ea adipisci eum debitis odit similique consectetur nesciunt ducimus maxime sed consequuntur repellendus qui illum vero necessitatibus perferendis cumque optio voluptatibus et quas velit voluptatem tempore est et officiis tempora iusto rerum eum amet a qui corrupti ex nobis laborum eum assumenda velit laboriosam et sed sapiente accusantium officia enim doloremque perspiciatis quos ut rerum molestias ut ut aut omnis vitae placeat voluptas iusto distinctio ea molestias et at et aliquam libero non neque dicta quos numquam est non explicabo ipsa neque dolores rerum.]]></description>
    <price><![CDATA[252.65 EUR]]></price>
    <url><![CDATA[https://example.com/product/2109]]></url>
    <image_url><![CDATA[http://lorempixel.com/640/480]]></image_url>
    <opening_times><![CDATA["1":["opening":"10:00","closing":"22:30"],"2":["opening":"10:00","closing":"22:30"],"3":["opening":"10:00","closing":"22:30"],"4":["opening":"10:00","closing":"22:30"],"5":["opening":"10:00","closing":"22:30"],"6":["opening":"10:00","closing":"22:30"],"7":[],"timezone":"Europe/Warsaw"]]></opening_times>
</offer>
<offer>
    <id><![CDATA[7673]]></id>
    <name><![CDATA[Ergonomic Soft Fish]]></name>
    <category><![CDATA[Rustic]]></category>
    <description><![CDATA[Pariatur consectetur autem reiciendis ab ea est fugiat tenetur suscipit ut sit rem accusamus accusamus accusamus veniam commodi omnis quia minus ratione reprehenderit est porro omnis modi et ipsa aut itaque impedit inventore modi nisi nemo commodi nesciunt earum quia sed assumenda nulla quia qui neque laborum vitae nobis dolorem perspiciatis tenetur nisi asperiores eos itaque dolorem sit est nostrum sequi similique doloremque vero id voluptas exercitationem eveniet saepe non impedit aut neque aut sed molestiae aut cum hic consectetur facilis porro atque perspiciatis maiores maiores ut aut enim iste maxime dolores est dolores quaerat dolores error nisi et esse voluptas occaecati nostrum quasi vero porro natus iste molestiae totam culpa vero voluptate porro aut ut iusto non ullam quam aut itaque velit quis maiores nobis officia ut iure voluptatibus iure nihil optio repellendus eum similique eum in excepturi doloremque rerum cumque accusantium fuga sed sed odit vel qui nam eum iure sapiente magni et temporibus quis qui pariatur tempora odit explicabo et mollitia autem nihil autem repellat ut et laudantium ab dolores nisi porro fuga sed laudantium quae delectus debitis quaerat doloremque praesentium quod ullam accusamus architecto earum impedit esse sint sint fugiat nihil itaque ut ut aut provident.]]></description>
    <price><![CDATA[384.12 EUR]]></price>
    <url><![CDATA[https://example.com/product/7673]]></url>
    <image_url><![CDATA[http://lorempixel.com/640/480]]></image_url>
    <opening_times><![CDATA["1":["opening":"14:00","closing":"23:00"],"2":["opening":"14:00","closing":"23:00"],"3":["opening":"14:00","closing":"23:00"],"4":["opening":"14:00","closing":"23:00"],"5":["opening":"14:00","closing":"23:00"],"6":["opening":"14:00","closing":"23:00"],"7":[],"timezone":"Europe/Warsaw"]]></opening_times>
</offer>
</offers>

我使用 XMLReader() 在所有 &lt;offer&gt; 中获得标记名称 &lt;opening_times&gt; 的值;通过以下代码:

<?php
$XMLReader = new XMLReader();
$XMLReader->open('feed_sample.xml');
while ($XMLReader->read())
    if ($XMLReader->name === 'offer' && $XMLReader->nodeType == XMLReader::ELEMENT)
        $element = array();
        $element = simplexml_load_string($XMLReader->readOuterXml());
        echo $element->opening_times;
    

但我只想从一个&lt;offer&gt; 获得价值&lt;opening_times&gt;,但我不知道该怎么做。

好的,我进一步创建了这样的代码。我是这样发明的:如果当前日期与&lt;opening_times&gt; 中给出的日期正确,请检查当前时间与&lt;opening_times&gt; 中给出的小时是否正确。这是我的第二个疑问。如果这些不是属性,如何从&lt;opening_times&gt; 获取日或小时的值?你能给我一个建议吗?

function compare_current_hour()
    $today = date('l');//aktualny dzień
    $now = date('h:i');//aktualna godzina
    if ($today === 'Monday')
        $day = 1;
     elseif ($today === 'Tuesday')
        $day = 2;
     elseif ($today === 'Wednesday')
        $day = 3;
     elseif ($today === 'Thursday')
        $day = 4;
     elseif ($today === 'Friday')
        $day = 5;
     elseif ($today === 'Saturday')
        $day = 6;
     elseif ($today === 'Sunday')
        $day = 7;
    

    if ($day === $day_xml)
        if ($now === $day_xml_opening_hours)
            //dodaj Tag Name <is_active>
        
    

希望不会太长。 非常感谢。

【问题讨论】:

【参考方案1】:

您已经在使用XMLReader::$name。这是元素节点的完整标签名称。我更喜欢使用XMLReader::$localName,它是没有命名空间别名的节点名。

XMLReader 用于大型 XML 文件。通常用于加载表示列表中项目的部件。然后该项目扩展为 DOM。这只会将一项 (offer) 节点及其后代加载到内存中。所以使用 XMLReader 的主要原因是内存消耗。它可以缩短处理时间,但前提是您在 XMLReader 级别进行过滤。根据我的经验,对于大多数情况而言,不值得付出额外的努力和复杂性。

您正在序列化和解析 XML 提要的一部分。 XMLReader 可以直接扩展成 DOM。然后您可以使用 Xpath 表达式从展开的节点中获取值:

$offerID = '7673';
$openingTimes = '[]';

$reader = new XMLReader();
$reader->open(getFeedURL());

// bootstrap a DOM document
$document = new DOMDocument();
$xpath = new DOMXpath($document);

// find the first "offer" element in the document
while ($reader->read() && $reader->localName !== 'offer') 
    continue;


// while the current node has the name "offer"
while ($reader->localName === 'offer') 
    
    // expand to DOM
    $offer = $reader->expand($document);
    // use Xpath to fetch ID
    $id = $xpath->evaluate('string(id)', $offer);
    // compare ID
    if ($offerID === $id) 
        // fetch opening times and break loop
        $openingTimes = $xpath->evaluate('string(opening_times)', $offer);
        break;
    
    
    // move to the next offer sibling
    $reader->next('offer');

$reader->close();

var_dump(json_decode($openingTimes, TRUE));

输出:

array(8) 
  [1]=>
  array(1) 
    [0]=>
    array(2) 
      ["opening"]=>
      string(5) "14:00"
      ["closing"]=>
      string(5) "23:00"
    
  
  [2]=>
  array(1) 
    [0]=>
    array(2) 
      ["opening"]=>
      string(5) "14:00"
      ["closing"]=>
      string(5) "23:00"
    
  
  ...

如果您不熟悉 Xpath 而更喜欢 SimpleXML,您可以导入 DOM 节点。

$offerID = '7673';
$openingTimes = '[]';

$reader = new XMLReader();
$reader->open(getFeedURL());

// bootstrap a DOM document
$document = new DOMDocument();

// find the first "offer" element in the document
while ($reader->read() && $reader->localName !== 'offer') 
    continue;


// while the current node has the name "offer"
while ($reader->localName === 'offer') 
    
    // expand to DOM
    $offerNode = $reader->expand($document);
    // import to SimpleXML
    $offer = simplexml_import_dom($offerNode);
    
    // cast first "id" child to string
    $id = (string)$offer->id;
    // compare ID
    if ($offerID === $id) 
        // read opening times and break loop
        $openingTimes = (string)$offer->opening_times;
        break;
    
    
    // move to the next offer sibling
    $reader->next('offer');

$reader->close();

var_dump(json_decode($openingTimes, TRUE));

如果提要足够小,您可以将其加载到 DOM 中并使用单个 Xpath 表达式来获取特定的打开时间:

$offerID = '7673';

$document = new DOMDocument();
$document->load(getFeedURL());
$xpath = new DOMXpath($document);

$openingTimes = $xpath->evaluate(
    "string(
      //offer[normalize-space(id) = '$offerID']
      /opening_times
    )"
);

var_dump(json_decode($openingTimes, TRUE));

或 SimpleXML:

$offerID = '7673';

$offers = simplexml_load_file(getFeedURL());
 
$opendingTimes = (string)(
  $offers->xpath(
    "//offer[normalize-space(id) = '$offerID']/opening_times"
  )[0] ?? ''    
);

var_dump(json_decode($openingTimes, TRUE));

【讨论】:

以上是关于如何在 XMLReader 中获取标记名称的值 + 如何使用该值进行进一步分析的主要内容,如果未能解决你的问题,请参考以下文章

如何在不扩展令牌的情况下获取 PATH 环境变量的值?

如何在本地反应中获取坐标并按城市名称放置标记?

JS如何获取值

PHP XMLReader 获取父节点?

深入认识XmlReader

如何在 uses-library 标记中获取 android:required (true 或 false) 属性的值?