Çocuk ve kılıp listelemek için PHP SimpleXML recursive fonksiyon

1 Cevap php

Ben SimpleXML bazı yardım elemanları adını ve özelliklerini listeleyen bir özyinelemeli işlev için çağırır gerekir. XML yapılandırma dosyası sistemi yapmak ama her script kendi config dosyasını yanı sıra yeni bir adlandırma kuralı olacak. Yani ne gerek niteliklere sahip tüm unsurları dışarı harita için kolay bir yoldur, bu nedenle gibi örnek 1'de tüm süreçleri aramak için basit bir yol gerekir ama ben unsurlar adıdır sabit kodlama olmadan bunu nasıl bilmiyorum işlev çağrısı. Yinelemeli bir alt öğe adı eşleştirmek için bir işlevi çağırmak için bir yolu var mı? Ben xpath işlevselliğini gördün ama ben nitelikleri için bu kullanmak için nasıl görmüyorum. Herhangi bir fikir?

Ayrıca örneklerde XML doğru görünmüyor mu? Bu gibi benim XML yapısı olabilir?

Örnek 1:

<application>
  <processes>
    <process id="123" name="run batch A" />
    <process id="122" name="run batch B" />
    <process id="129" name="run batch C" />
  </processes>
  <connections>
    <databases>
      <database usr="test" pss="test" hst="test" dbn="test" />
    </databases>
    <shells>
      <ssh usr="test" pss="test" hst="test-2" />
      <ssh usr="test" pss="test" hst="test-1" />
    </shells>
  </connections>
</application>

Örnek 2:

<config>
  <queues>
    <queue id="1" name="test" />
    <queue id="2" name="production" />
    <queue id="3" name="error" />
  </queues>
</config>

Sahte kod:

// Would return matching process id
getProcess($process_id) {
  return the process attributes as array that are in the XML
}

// Would return matching DBN (database name)
getDatabase($database_name) {
  return the database attributes as array that are in the XML
}

// Would return matching SSH Host
getSSHHost($ssh_host) {
  return the ssh attributes as array that are in the XML
}

// Would return matching SSH User
getSSHUser($ssh_user) {
  return the ssh attributes as array that are in the XML
}

// Would return matching Queue 
getQueue($queue_id) {
  return the queue attributes as array that are in the XML
}

EDIT:

Ben iki Parms geçebilir? Eğer Gordon @ önerdi ilk yöntem üzerinde

Ben sadece thnx, aşağıya bakınız, got it

public function findProcessById($id, $name)
{
    $attr = false;
    $el = $this->xml->xpath("//process[@id='$id'][@name='$name']"); // How do I also filter by the name?
    if($el && count($el) === 1) {
        $attr = (array) $el[0]->attributes();
        $attr = $attr['@attributes'];
    }
    return $attr;
}

1 Cevap

XML bana iyi görünüyor. O boşluk içerir ve bir textnode olmalı çünkü ben yapmayacağım tek şey o zaman (bence), process in name bir niteliği yapıyor. SimpleXML bu konuda şikayet değil ama beri, ben kişisel tercihinize aşağı kaynar sanırım.

Ben büyük olasılıkla XPath sorguları sarması, bir DataFinder sınıf ile bu yaklaşım olur, örneğin

class XmlFinder
{
    protected $xml;
    public function __construct($xml)
    {
        $this->xml = new SimpleXMLElement($xml);
    }
    public function findProcessById($id)
    {
        $attr = false;
        $el = $this->xml->xpath("//process[@id='$id']");
        if($el && count($el) === 1) {
            $attr = (array) $el[0]->attributes();
            $attr = $attr['@attributes'];
        }
        return $attr;
    }
    // ... other methods ...
}

ve daha sonra kullanmak

$finder = new XmlFinder($xml);
print_r( $finder->findProcessById(122) );

Çıktı:

Array
(
    [id] => 122
    [name] => run batch B
)

XPath öğretici:


Alternatif SimpleXmlIterator öğeleri üzerinde yineleme için kullanmak olacaktır. Iterators decorated diğer iteratörler olabilir, bu yüzden bunu yapabilirsiniz:

class XmlFilterIterator extends FilterIterator
{
    protected $filterElement;
    public function setFilterElement($name)
    {
        $this->filterElement = $name;
    }
    public function accept()
    {
        return ($this->current()->getName() === $this->filterElement);
    }
}

$sxi = new XmlFilterIterator(
           new RecursiveIteratorIterator( 
               new SimpleXmlIterator($xml)));

$sxi->setFilterElement('process');

foreach($sxi as $el) {
    var_dump( $el ); // will only give process elements
}

Siz özellikleri için filtre iş var biraz daha yöntemleri eklemek olurdu, ama bu oldukça önemsiz bir iştir.

SplIterators Giriş: