【问题标题】:Adding additional string to variable - PHP向变量添加附加字符串 - PHP
【发布时间】:2016-11-15 18:00:30
【问题描述】:

这是我的问题。我想创建一个函数,它接受一个包含 xpath 的外部变量,一旦函数运行,我想添加到同一个变量以创建一个计数器。

所以我有外部变量:

 $node = $xmlDoc->xpath('//a:Order');

然后是带有单个参数的函数,它将采用外部变量 ($node)。像这样:

function loopXML($node) {
    i=1; //counter variable
}

现在我想向 $node 添加一个计数器,以便它通过“Order”的所有子级。在函数之外,我会使用:

$child = $xmlDoc->xpath('//a:Order['.$i.']/*'); 

但在函数内部,我不知道如何连接它。有谁知道我该怎么做?

编辑: 另外,应该注意的是,我已经创建了一个任意命名空间:

 foreach($xmlDoc->getDocNamespaces() as $strPrefix => $strNamespace) {
     if(strlen($strPrefix)==0) {
         $strPrefix="a"; //Assign an arbitrary namespace prefix.
     }
     $xmlDoc->registerXPathNamespace($strPrefix,$strNamespace);
 }

【问题讨论】:

  • 你为什么将$node 传递给函数?它是如何使用的?
  • 该函数的目标是将xml转换为csv。 $node 是要循环通过的 xml 父 xml 标记。 $child 是 $node 的所有子节点。我不得不做很多事情,所以我想创建一个函数来减少冗余,所以我可以只包含我想要提取的 xpath(或 xml 标签)。
  • 另外,为什么不在原始节点上使用$xml->children() 属性以便迭代它们?
  • 因为我不知道!谢谢!我会试一试,看看它是否有效。如果有我会发帖的。
  • 我试过 $nodeC = $nodeP->childNodes;在函数中,但它不起作用。

标签: php xml xpath concat


【解决方案1】:

SimpleXMLElement::xpath() 使用与 SimpleXML 元素关联的节点作为上下文,因此您可以执行以下操作:

foreach ($xmlDoc->xpath('//a:Order') as $order) {
  foreach ($order->xpath('*') as $field) {
    ...
  }
} 

但 SimpleXMLElement::children() 是元素子节点的列表,因此它返回的结果与 Xpath 表达式 * 或更准确地说是 '*[namespace-uri == ""]' 相同。第一个参数是您要获取的孩子的命名空间。

foreach ($xmlDoc->xpath('//a:Order') as $order) {
  foreach ($order->children() as $field) {
    ...
  }
}

这可以很容易地重构为一个函数。

function getRecord(SimpleXMLelement $order, $namespace) {
  $result = [];
  foreach ($order->children($namespace) as $field) {
    $result[$field->getName()] = (string)$field;
  }
  return $result;
}

您应该始终依赖于实际的命名空间,而不是前缀。前缀可以更改并且是可选的。

放在一起:

$xml = <<<'XML'
<a:orders xmlns:a="urn:a">
  <a:order>
    <a:foo>bar</a:foo>
    <a:answer>42</a:answer>
  </a:order>
</a:orders>
XML;

$namespace = 'urn:a';

$orders = new SimpleXMLElement($xml);
$orders->registerXpathNamespace('a', $namespace);

function getRecord(SimpleXMLelement $order, $namespace = NULL) {
  $result = [];
  foreach ($order->children($namespace) as $field) {
    $result[$field->getName()] = (string)$field;
  }
  return $result;
} 

foreach ($orders->xpath('//a:order') as $order) {
  var_dump(getRecord($order, $namespace));
}

输出:

array(2) {
  ["foo"]=>
  string(3) "bar"
  ["answer"]=>
  string(2) "42"
}

【讨论】:

  • 我试过这个,但似乎没有让它工作。值得注意的是,我已经创建了一个任意命名空间。
  • 其中一个限制是,如果在表达式中使用它们,则必须在调用 xpath() 的每个 SimpleXMLElement 上注册命名空间。
【解决方案2】:

所以我通过大量的谷歌搜索和 ThW 的帮助想通了。所以对所有帮助过的人,谢谢。这是我如何让它工作的:

 $orderPNode = '//a:Order'; 
 $amazonRawXML = 'AmazonRaw.xml';
 $amazonRawCSV = 'AmazonRaw.csv';


function loopXML($xmlDoc, $node, $writeCsv) {
$i = 1;
$xmlDocs = simplexml_load_file($xmlDoc);
$result = [];

foreach($xmlDocs->getDocNamespaces() as $strPrefix => $strNamespace) {
    if(strlen($strPrefix)==0) {
        $strPrefix="a"; //Assign an arbitrary namespace prefix.
    }
$xmlDocs->registerXPathNamespace($strPrefix,$strNamespace);
}

file_put_contents($writeCsv, ""); // Clear contents of csv file after each go

$nodeP = $xmlDocs->xpath($node); 

foreach ($nodeP as $n) {
    $nodeC = $xmlDocs->xpath($node.'['.$i.']/*');
    if($nodeC) {
        foreach ($nodeC as $value) {
            $values[] = $value;
        }
    $write = fopen($writeCsv, 'a'); 
    fputcsv($write, $values);
    fclose($write);

    $values = [];
    $i++;
    } else {
        $result[] = $n;
        $i++;
    }

}
return $result;
}
loopXML($amazonRawXML, $orderPNode, $amazonRawCSV);

【讨论】:

    猜你喜欢
    • 2016-07-14
    • 2023-03-13
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 2013-03-26
    • 2012-05-24
    • 1970-01-01
    • 2010-11-20
    相关资源
    最近更新 更多