كيفية سرد كائنات SimpleXML التي تمثل العنصر وسمة؟

StackOverflow https://stackoverflow.com/questions/724935

  •  05-09-2019
  •  | 
  •  

سؤال

أحتاج إلى الطباعة اعتباطيا كائنات SimpleXML بطريقة محددة، مع معالجة خاصة لعقد السمة.

المشكلة هي أن عناصر وسمات SimpleXML تبدو تستخدم بالضبط نفس الفئة، وعقدة السمة تتظاهر بالدعم attributes() الطريقة، ويقوم SimpleXML بإخفاء Internal Internal، لذلك لا يبدو أن هناك بأي حال من الأحوال لإخبار نوع العقدة (قصيرة توليد XML وإعادة تكوينه).

كلاهما يعطي تطابق نتيجة:

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

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

هل هناك خاصية / طريقة خفية تسمح بتحديد نوع العقدة في SimpleXML؟ أي ما يعادل دوم $node->nodeType أو $node instanceof DOMAttrب (لا يمكنني استخدام DOM بدلا من ذلك، ودعم SimpleXML هو الشرط الأساسي).

هل كانت مفيدة؟

المحلول

لا توجد عقارات مدمجة في SimpleXMLElement والتي من شأنها أن تسمح لك بإخبارها هذه بصرف النظر.

كما اقترح الآخرون dom_import_simplexml يمكن أن تكون مناسبة، ومع ذلك، يمكن أن تؤدي هذه الوظيفة إلى تغيير العقد على ذبابة أحيانا، على سبيل المثال، إذا مرت في قائمة الأطفال أو الأطفال الذين يحملون تحمل اسم الأطفال، فسوف يستغرق الأمر من العناصر الأولى.

إذا كانت قائمة فارغة، على سبيل المثال لا توجد سمات تم إرجاعها من attributes() أو غير موجود يدعى الأطفال، وسوف يعطي تحذيرا يخبرك أنه قد أعطيت لك NodeType غير صالح:

تحذير: DOM_IMPORT_SIMPLEXML (): NodeType غير صالح للاستيراد

لذلك إذا كنت بحاجة إلى هذا الدقة مع منطقية true/false, ، إليك كيفية عملها مع SimpleXML:

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

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

يعمل مماثلة مع قوائم السمة وقوائم العناصر، لقد بلوج فقط حول هذا في الصباح, ، يجب أن يكون لديك بعض المعرفة المحددة حول ما يجب تقييمه مقابل ما، لذلك قمت بإنشاء غشية له:

+------------------+---------------------------------------------+
| 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)    |
+------------------+---------------------------------------------+

نصائح أخرى

نعم، ثمة طريق. حسنا، لا شيء أنيق يمكنك استرداده عبر API، ولكن في مكان ما في الشجاعة من SimpleXML هو تتبع ما هو عليه، ويجعل الاختلافات، على سبيل المثال، عند استدعاء الوظائف مثل GetName () أو ASXML ().

$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"

لن يفوز الكود الخاص بك في مسابقة الجمال، ولكن على الأقل يمكنك القيام بذلك.

باستخدام ما أشار بالاكو، قد تعمل وظيفة مثل هذا:

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

انت تحتاج Simplexmlelement :: سمات:

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 . '>';

}

قد تحتاج قليلا من التغيير والتبديل.

هل هناك خاصية / طريقة خفية تسمح بتحديد نوع العقدة في SimpleXML؟ ما يعادل DOM's $ العقدة> NodeType أو $ العقدة instanceof domattr؟ (لا يمكنني استخدام DOM بدلا من ذلك، ودعم SimpleXML هو الشرط الأساسي)

الجواب ليس ... ونعم. ليس لدى Simplexml مثل هذه الممتلكات ولكن هذه الأخبار الجيدة: Simplexml و Dom هي وجاوعتين من نفس العملة المعدنية. (العملة libxml؛)) ليس لديك لاختيار واحد أو آخر، يمكنك استخدام كلاهما! يمكنك التحول SimpleXMLElement إلى DOMNode والعكس صحيح. في حالتك، يمكنك القيام بشيء مثل:

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

إذا كان هذا شيء تفعله في كثير من الأحيان، أو لا ترغب في التعامل مع شعوذة DOM / SimpleXML، فيمكنك إلقاء نظرة على spepledom..

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

لسوء الحظ، لا توجد خاصية أو طريقة خفية تسمح بتحديد نوع العقدة في SimpleXML. يستخدم Simplexml فقط فئة واحدة وعناصر لا تملك أي شيء يشير إلى والديهم. إذا حاولت الانعكاس أدناه، فسترى أنه لا يوجد شيء لتمييز العنصر أو السمة.

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

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

ومع ذلك، إذا كان عنصر قد سمات يمكنك اكتشاف ذلك. لذلك عليك أن تفترض أن جميع العناصر مرت بها سمات. مع هذا الافتراض، يمكنك أن تقول لهم بعيدا.

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

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

هذا هو أفضل ما يمكنني التوصل إليه. تذكر أنه من الممكن لعنصر عدم وجود سمات لا يزال بإرجاع خطأ مع هذا.

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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top