2016-11-15 4 views
0

Вот моя проблема. Я хочу создать функцию, которая принимает внешнюю переменную, которая содержит xpath, и как только функция запускается, я хочу добавить к этой же переменной для создания счетчика.Добавление дополнительной строки в переменную - PHP

Так что есть за пределами переменной:

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

Тогда функция с одним аргументом, который будет принимать внешнюю переменную ($node). Как так:

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

Теперь я хочу, чтобы добавить счетчик в $ узел так, что она проходит через все дети «Заказ». Вне зависимости, я хотел бы использовать:

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

Но внутри функции, я понятия не имею, как Concat его. Кто-нибудь знает, как я могу это сделать?

EDIT: Кроме того, следует отметить, что я создал произвольное пространство имен уже:

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

Почему вы передаете функцию '$ node' в функцию? Как он используется? – AbraCadaver

+0

Целью функции является преобразование xml в csv. $ node - xml parent xml tag для циклического перехода. $ child - все дети $ node. Мне нужно сделать это много, поэтому я хотел бы создать функцию для сокращения избыточности, и поэтому я могу просто включить xpath (или xml-тег), который я хочу извлечь. – Twigs

+0

Кроме того, почему бы не использовать свойство [$ xml-> children()] (http://php.net/manual/en/simplexmlelement.children.php) на вашем исходном узле, чтобы вы могли повторять их? –

ответ

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" 
} 
+0

Я пробовал это, но, похоже, не работал.Возможно, стоит отметить, что я уже создал произвольное пространство имен. – Twigs

+0

Один из ограничений заключается в том, что вам придется регистрировать пространства имен на каждом SimpleXMLElement, который вы вызываете 'xpath()', если вы используете их в выражении. – ThW

0

Так что я решил, что с большим количеством Googling и помощи 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);