向变量添加额外的字符串 - PHP
Adding additional string to variable - PHP
这是我的问题。我想创建一个函数,它接受一个包含 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);
}
SimpleXMLElement::xpath()
使用与 SimpleXML 元素关联的节点作为上下文,因此您可以执行如下操作:
foreach ($xmlDoc->xpath('//a:Order') as $order) {
foreach ($order->xpath('*') as $field) {
...
}
}
但是 SimpleXMLElement::children() 是元素子节点的列表,因此它 returns 与 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"
}
所以我通过大量谷歌搜索和 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);
这是我的问题。我想创建一个函数,它接受一个包含 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);
}
SimpleXMLElement::xpath()
使用与 SimpleXML 元素关联的节点作为上下文,因此您可以执行如下操作:
foreach ($xmlDoc->xpath('//a:Order') as $order) {
foreach ($order->xpath('*') as $field) {
...
}
}
但是 SimpleXMLElement::children() 是元素子节点的列表,因此它 returns 与 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"
}
所以我通过大量谷歌搜索和 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);