Recursive fonksiyon içinde xml düğüm XPath alın

5 Cevap php

I recursively böyle bir XML dosyası üzerinden yineleme için bazı kod var diyelim:

$xmlfile = new SimpleXMLElement('http://www.domain.com/file.xml',null,true);
xmlRecurse($xmlfile,0);
function xmlRecurse($xmlObj,$depth) {
  foreach($xmlObj->children() as $child) {
    echo str_repeat('-',$depth).">".$child->getName().": ".$subchild."\n";
    foreach($child->attributes() as $k=>$v){
        echo "Attrib".str_repeat('-',$depth).">".$k." = ".$v."\n";
    }
    xmlRecurse($child,$depth+1);
  }
}

Nasıl her düğümün xpath hesaplar yüzden diğer kodu haritalama için saklayabilirsiniz?

5 Cevap

Bunu yapmak için belirgin şekilde üçüncü bir parametre olarak XPath geçmek ve derin kazmak gibi inşa etmektir. Sen aynı adı taşıyan kardeşleri için hesap var, yani yineleme sırasında mevcut çocuk olarak aynı adı taşıyan emsal kardeş sayısını takip etmek zorunda.

Çalışma örneği:

function xmlRecurse($xmlObj,$depth=0,$xpath=null) {
  if (!isset($xpath)) {
    $xpath='/'.$xmlObj->getName().'/';
  }
  $position = array();

  foreach($xmlObj->children() as $child) {

    $name = $child->getName();
    if(isset($position[$name])) {
      ++$position[$name];
    }
    else {
      $position[$name]=1;
    }
    $path=$xpath.$name.'['.$position[$name].']';

    echo str_repeat('-',$depth).">".$name.": $path\n";
    foreach($child->attributes() as $k=>$v){
        echo "Attrib".str_repeat('-',$depth).">".$k." = ".$v."\n";
    }

    xmlRecurse($child,$depth+1,$path.'/');
  }
}

Dikkat olsa, bütün bir belge eşleme ve yol boyunca XPath'i saklama fikrine garip görünüyor. Aslında tamamen farklı bir sorunun yanlış çözüm üzerinde çalışıyor olabilir.

Sen xmlRecurse (geçerli düğüm xPath gösterimi ile) $ xpath denilen üçüncü param geçmek ve her tekrarında çocukların xpath temsilini ekleyebilirsiniz:

function xmlRecurse($xmlObj,$depth,$xpath) {
  $i=0;
  foreach($xmlObj->children() as $child) {
    echo str_repeat('-',$depth).">".$child->getName().": ".$subchild."\n";
    foreach($child->attributes() as $k=>$v){
        echo "Attrib".str_repeat('-',$depth).">".$k." = ".$v."\n";
    }
    xmlRecurse($child,$depth+1,$xpath.'/'.$child->getName().'['.$i++.']');
  }
}

Bir dize argüman olarak düğüm yolu recursing göre: SimpleXML ile, diğerleri işaret gibi sadece bunu düşünüyorum.

DOMDocument ile, geri belge elemanı için tarama $node->parentNode özelliğini kullanabilir ve bir düğüme bir başvuru vardı ve ağaç nerede olduğunu keşfetmek istiyorsa (örneğin bir keyfi düğüm için inşa Eğer bu düğüme var nasıl önceden bilgisi olmadan).

$domNode = dom_import_simplexml($node);
$xpath = $domNode->getNodePath();

Bu çalışması için PHP 5> = 5.2.0 gerekir.

Yararlar hakkında MightyE fikri takip etmek:

function whereami($node)
{
    if ($node instanceof SimpleXMLElement)
    {
        $node = dom_import_simplexml($node);
    }
    elseif (!$node instanceof DOMNode)
    {
        die('Not a node?');
    }

    $q     = new DOMXPath($node->ownerDocument);
    $xpath = '';

    do
    {
        $position = 1 + $q->query('preceding-sibling::*[name()="' . $node->nodeName . '"]', $node)->length;
        $xpath    = '/' . $node->nodeName . '[' . $position . ']' . $xpath;
        $node     = $node->parentNode;
    }
    while (!$node instanceof DOMDocument);

    return $xpath;
}

Ben (bir tek verilen düğüm aksine, bir bütün belge eşleme) eldeki durum için bunu tavsiye etmem ama ileride başvurmak için yararlı olabilir.