使用php迭代不同的DOM节点和元素

时间:2013-12-23 16:46:59

标签: php html xml string dom

我正在尝试根据时间条件创建简报。我有一个XML文件加载到DOM文档中。

<?xml version="1.0"?>
<users>
<user><mail>sandro.calzada@gmail.com</mail><time>1387814834</time></user><user>       <mail>b4bp_22@hotmail.com</mail><time>1387814834</time></user></users>

我希望遍历所有'time'标记,同时将每个'mail'标记中的值作为字符串获取。

这是我的第一次尝试。我不知道为什么我在这里失败了,但似乎迭代在时间上工作正常,但留下了邮件。

    $data = new DOMDocument();

$data->load('data.xml');

$times = $data->getElementsByTagName('time');
$emails = $data->getElementsByTagName('mail');

$timestamp = time();
$timestamp1 = $timestamp;
$timestamp = $timestamp-1;

foreach($times as $t)

{

    if($t->nodeValue > $timestamp)

    {

    }

    else if($t->nodeValue < $timestamp)

{

$t->nodeValue = $timestamp1;

$email = $emails->nodeValue;

$to = $email;

这是我的第二次尝试。这里的问题是$ email无法转换为字符串。

$itm = 0;

require_once('functions.php');

$data = new DOMDocument();

$data->load('data.xml');

$times = $data->getElementsByTagName('time');

$timestamp = time();
$timestamp1 = $timestamp;
$timestamp = $timestamp-1;

foreach($times as $t)

{

    if($t->nodeValue > $timestamp)

    {
    $itm = $itm+1;
    }

    else if($t->nodeValue < $timestamp)

{

$t->nodeValue = $timestamp1;

$email1 = $data->getElementsByTagName('mail')->item($itm);

$email = strval($email1);

$itm = $itm+1;

$to = $email;

$unsub = base64_encode($email);

我有什么想法可以做到这一点?谢谢你的帮助!

4 个答案:

答案 0 :(得分:0)

for循环可能更合适:

$times = $data->getElementsByTagName('time');
$emails = $data->getElementsByTagName('mail');

for ($i=0; $i < $times->length; $i++) { 
    $ts = (string) $times->item(0)->nodeValue;
    if ( $ts < time()-1 ) {
        $times->item(0)->nodeValue = $ts;
        $email = $emails->item(0)->nodeValue;
    }
}

Demo.

答案 1 :(得分:0)

我认为这样会更具可读性:

<?php
$x='<?xml version="1.0"?>
<users>
<user><mail>sandro.calzada@gmail.com</mail><time>1387814834</time></user>
<user>       <mail>b4bp_22@hotmail.com</mail><time>1387814834</time></user></users>';
$doc = new DOMDocument();
$doc->loadXML($x);

foreach ($doc->getElementsByTagName('user') as $user){
   $mails = $user->getElementsByTagName('mail');
   $times = $user->getElementsByTagName('time');
   print $mails->item(0)->nodeValue. "-". $times->item(0)->nodeValue ."\n";
}

您可以在此处尝试:https://eval.in/82242

答案 2 :(得分:0)

我修改了Amal代码,这正是我需要的。

    $times = $data->getElementsByTagName('time');
$emails = $data->getElementsByTagName('mail');

$timestamp = time();

for ($i=0; $i < $times->length; $i++) { 
$ts = (string) $times->item($i)->nodeValue;
if ( $ts < $timestamp-1 ) {
    $times->item($i)->nodeValue = $timestamp;
    $email = $emails->item($i)->nodeValue;

$to = $email;

答案 3 :(得分:0)

您希望将XML元素(可能还有属性)作为字符串进行访问。您已选择PHP的DOMDocument库来解析XML。 DOM is a standard defined by W3C不仅被PHP使用,还被许多其他人使用,例如Mozilla。

要获取具有DOMDocument的元素的字符串值,您需要访问nodeValue对象的DOMElement属性(PHP:DOMElement::$nodeValue),它实际上是{{DOMNode的一部分。 1}}(PHP:DOMNode::$noveValueDOMElementDOMNode的子类型。 PHP手册说明了nodeValue

  

的nodeValue
  此节点的值,取决于其类型

通过 type ,这意味着如果类型为DOMElement(如您的情况),则它将包含您正在寻找的字符串。

所以你需要做的就是查询那些 time 元素之前的所有那些 email 元素(在我的例子中我翻转它:lower)比时间比较:

$doc = new DOMDocument;
$doc->loadXML($xml);
$xpath = new DOMXpath($doc);

$expr  = sprintf(
    '//user/time[number(.) < %d]/preceding-sibling::mail[last()]'
    , time()
);
echo '"', $expr, "\" :\n";

$emails = $xpath->query($expr);
foreach($emails as $email) {
    echo ' * ', $email->nodeValue, "\n";
}

如此示例所示,$email->nodeValue包含电子邮件地址为字符串。与示例性输出相比:

"//user/time[number(.) < 1387896441]/preceding-sibling::mail[last()]" :
 * sandro.calzada@gmail.com
 * b4bp_22@hotmail.com

演示在这里:https://eval.in/82540


对于您在问题中使用的XML,使用PHP具有的不同(但相关)XML解析器更容易访问: SimpleXML 。与以下示例比较:

$doc = simplexml_load_string($xml);

$expr  = sprintf(
    '//user/time[number(.) < %d]/preceding-sibling::mail[last()]'
    , time()
);

$emails = $doc->xpath($expr);
foreach($emails as $email) {
    echo ' * ', $email, "\n";
}

正如此示例所示,SimpleXML提供了神奇的__toString()方法,以便电子邮件的元素对象 - $email - 在与echo一起使用时自动转换为字符串。

演示在这里:https://eval.in/82545