Nasıl ögenin SimpleXML nesneleri ayırt ve atfetmek?

6 Cevap php

Ben öznitelik düğümleri özel kargo ile, belirli bir şekilde arbitrary SimpleXML nesneleri yazdırmak gerekiyor.

Sorun SimpleXML elemanları ve nitelikleri hatta attributes() yöntemini desteklemek için miş, ve SimpleXML onun iç gizler, yani türünü anlatmak için herhangi bir yol olarak görünmüyor öznitelik düğümünü, aynı sınıfını kullanmak gibi olduğunu düğüm (XML oluşturma ve yeniden çözümlenerek kısa) arasında.

Her iki identical sonuç verir:

$element = new SimpleXMLElement('<foo>test</foo>');
echo $element;
print_r($element);

$element = new SimpleXMLElement('<foo attr="test" />');
echo $element['attr'];
print_r($element['attr']);

SimpleXMLElement düğüm tipini tanımlayan sağlayan bir gizli özellik / yöntem var mı? Eşdeğer DOM $node->nodeType veya $node instanceof DOMAttr? (Ben SimpleXML desteği temel gereksinimi olduğunu, bunun yerine DOM kullanmak olamaz).

6 Cevap

Eğer bunların dışında anlatmak için izin verecek SimpleXMLElement hiçbir yerleşik özellikleri vardır.

Diğerleri dom_import_simplexml uygun olabilir ileri sürdüğümüz gibi, ancak, bu işlevi ChildNodes veya adlandırılmış ChildNodes listesinde geçirirseniz, bunun bu alacak, örneğin, bazen anında düğümleri değiştirebilirsiniz ve ilk elemanı onları açın.

Boş bir liste varsa, örneğin hiçbir nitelikler attributes() döndürülen veya adlandırılmış childNodes mevcut olmayan, geçersiz bir DüğümTürü verilmiştir söyleyen bir uyarı verecektir:

Uyarı: dom_import_simplexml (): Geçersiz nodeType almak

Eğer bir sallanma boolean ile bu kesin gerekirse Yani true / false, burada SimpleXML ile nasıl işliyor:

$isElement   = $element->xpath('.') == array($element);

$isAttribute = $element[0] == $element
               and $element->xpath('.') != array($element);

Ben just blogged about this in the morning, sen ne için değerlendirmek gerekenler hakkında bazı özel bilgi olması gerekir, o yüzden ben bunun için bir Klavuzu yarattı, nitelik listeleri ve eleman listeleri ile benzer çalışır:

+------------------+---------------------------------------------+
| TYPE             | TEST                                        |
+------------------+---------------------------------------------+
| Element          | $element->xpath('.') == array($element)     |
+------------------+---------------------------------------------+
| Attribute        | $element[0] == $element                     |
|                  | and $element->xpath('.') != array($element) |
+------------------+---------------------------------------------+
| Attributes       | $element->attributes() === NULL             |
+------------------+---------------------------------------------+
| Elements         | $element[0] != $element                     |
|                  | and $element->attributes() !== NULL         |
+------------------+---------------------------------------------+
| Single           | $element[0] == $element                     |
+------------------+---------------------------------------------+
| Empty List       | $element[0] == NULL                         |
+------------------+---------------------------------------------+
| Document Element | $element->xpath('/*') == array($element)    |
+------------------+---------------------------------------------+

Evet bir yolu yoktur. Böyle getName () veya asXML () gibi fonksiyonları çağırdığınızda Peki, API aracılığıyla almak, ama bir yerde SimpleXML cesareti olduğunu zarif bir şey ne olduğunu takip tutuyor ve bu farklılıklar yapar, örneğin.

$element = new SimpleXMLElement('<foo>test</foo>');
print_r($element->getName());
print_r($element->asXML());
echo "------------------\n";
$element = new SimpleXMLElement('<foo attr="test" />');
$at = $element['attr'];
print_r($at->getName());
print_r($at->asXML());

foo
<?xml version="1.0"?>
<foo>test</foo>
------------------
attr 
attr="test"

Kodunuzu bir güzellik yarışmasını kazanmak değil, ama en azından bunu yapabilirsiniz.

Işaret palako kullanarak ne, böyle bir fonksiyon işe yarayabilir:

function is_attribute($node) {
    return !($node->asXML()[0] == "<")
}

İhtiyacınız SimpleXMLElement::attributes:

function xml_out($el) {
    $name = $el->getName();
    echo '<'. $name;

    if (count($el->attributes())) {
        foreach ($el->attributes() as $a=>$v) {
            echo ' '. ((string)$a) . '="' . htmlspecialchars((string)$v) . '"';
        }
    }

    echo '>'. (string)$el;

    if (count($el->children())) {
        foreach($el->children() as $c) {
            xml_out($c);
        }
    }
    echo '</'. $name . '>';

}

Verdiği biraz gerekebilir.

SimpleXMLElement düğüm tipini tanımlayan sağlayan bir gizli özellik / yöntem var mı? DOMAttr instanceof DOM $ node-> nodeType ya $ düğümün Eşdeğer? (Ben bunun yerine DOM kullanmak değil, SimpleXML için destek çekirdek gerekliliktir)

Cevap hayır ... ve evet. SimpleXML böyle bir özelliği yok ama burada iyi haber: SimpleXML ve DOM aynı madalyonun iki yüzüdür. (the coin is libxml ;)) birini veya diğerini seçmek zorunda değilsiniz, hem de kullanabilirsiniz! Sen tam tersi SimpleXMLElement DOMNode dönüşebilir edebilirsiniz. Senin durumunda, gibi bir şey yapabilirsiniz:

$element = new SimpleXMLElement('<foo attr="test" />');
$is_attr = (dom_import_simplexml($element['attr'])->nodeType === XML_ATTRIBUTE_NODE);

Böyle sık sık yapmak veya DOM / SimpleXML hokkabazlık işlemek istemiyorsanız bir şey varsa, SimpleDOM de bir göz atabilirsiniz.

$element = new SimpleDOM('<foo attr="test" />');
$is_attr = ($element['attr']->nodeType() === XML_ATTRIBUTE_NODE);

Ne yazık ki hiçbir gizli özellik veya SimpleXMLElement düğüm türünü tanımlayan olanak sağlayan bir yöntem yoktur. SimpleXML tek Class kullanır ve elemanları ebeveynleri işaret şey yok. Eğer aşağıda yansımasını denerseniz öğe veya öznitelik ayırmak şey olduğunu göreceksiniz.

$element = new SimpleXMLElement('<foo>test</foo>');
echo ReflectionObject::export($element);

$element = new SimpleXMLElement('<foo attr="test">test</foo>');
echo ReflectionObject::export($element['attr']);

Bir eleman öznitelikleri Ancak eğer olduğunu tespit edebilirsiniz. Yani geçirilen tüm unsurları özelliklere sahip olduğunu varsaymak gerekir. Bu varsayıma ile onlara ayrı söyleyebilirdi.

$element = new SimpleXMLElement('<foo attr="test">test</foo>');

echo ReflectionObject::export($element);
echo ReflectionObject::export($element['attr']);

Bu ben ile gelebilir en iyisidir. Hala bu ile return false için hiçbir niteliklere sahip bir eleman için mümkün hatırlıyorum.

function isNotAttribute($simpleXML)
{
  return (count($simpleXML->attributes()) > 0);
}

$element = new SimpleXMLElement('<foo attr="test">test</foo>');
var_dump(isNotAttribute($element));
var_dump(isNotAttribute($element['attr']));

// returns
bool(true)
bool(false)