Twigs Twigs - 19 days ago 5
PHP Question

Adding additional string to variable - PHP

Here's my problem. I want to create a function that takes an outside variable that contains an xpath and once the function runs I want to add to that same variable to create a counter.

So I have the outside variable:

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


Then the function with a single argument that will take the outside variable (
$node
). Like so:

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


Now I want to add a counter to $node so that it goes through all of the children of "Order". Outside of the function, I would use:

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


But inside of the function, I have no idea how to concat it. Does anyone have any idea how I could do this?

EDIT:
Also, it should be noted that I created an arbitrary namespace already:

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

ThW ThW
Answer

SimpleXMLElement::xpath() uses the node associated with the SimpleXML element as the context so you can do something like:

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

But SimpleXMLElement::children() is a list of the element child nodes so it returns the same as the Xpath expression * or to be more exact '*[namespace-uri == ""]'. The first argument is the namespace of the children you would like to fetch.

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

This can be easily refactored into a function.

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

You should always depend on the actual namespace, never on the prefix. Prefixes can change and are optional.

Put all together:

$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));
}

Output:

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