سؤال

وأنا بحاجة للحصول على محتويات HTML من answer في هذا قليلا من XML:

<qa>
 <question>Who are you?</question>
 <answer>Who who, <strong>who who</strong>, <em>me</em></answer>
</qa>

وهكذا أريد للحصول على سلسلة "من الذين، على الذي الذي و <م> لي ".

إذا لدي answer باعتباره SimpleXMLElement، يمكن أن أدعو asXML() للحصول على "<الجواب> من منظمة الصحة العالمية، على الذي الذي و <م> لي "، ولكن كيفية الحصول على XML الداخلي للعنصر دون عنصر نفسها ملفوفة حول ذلك؟

وكنت تفضل الطرق التي لا تنطوي على وظائف سلسلة، ولكن إذا كان هذا هو السبيل الوحيد، فليكن ذلك.

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

المحلول

لوعلمي، ليس هناك المدمج في طريقة للحصول على ذلك. فما استقاموا لكم فاستقيموا أوصى تحاول SimpleDOM ، التي هي فئة PHP توسيع SimpleXMLElement أن أساليب العروض الراحة بالنسبة لمعظم من المشاكل المشتركة.

include 'SimpleDOM.php';

$qa = simpledom_load_string(
    '<qa>
       <question>Who are you?</question>
       <answer>Who who, <strong>who who</strong>, <em>me</em></answer>
    </qa>'
);
echo $qa->answer->innerXML();

وعلى خلاف ذلك، وأرى طريقتين للقيام بذلك. سوف يكون أول لتحويل SimpleXMLElement الخاص بك إلى DOMNode ثم حلقة على childNodes لبناء XML. ان البعض يكون لاستدعاء asXML() ثم استخدام وظائف سلسلة لإزالة عقدة الجذر. الاهتمام على الرغم من asXML() أحيانا قد يعود العلامات التي هي في الواقع <م> خارج العقدة كان يطلق عليه من مثل حاسوب XML أو معالجة التعليمات.

نصائح أخرى

function SimpleXMLElement_innerXML($xml)
  {
    $innerXML= '';
    foreach (dom_import_simplexml($xml)->childNodes as $child)
    {
        $innerXML .= $child->ownerDocument->saveXML( $child );
    }
    return $innerXML;
  };

وهذا يعمل (على الرغم من أنه يبدو حقا عرجاء):

echo (string)$qa->answer;

والحل الأكثر وضوحا هو تنفيذ مخصص الحصول innerXML مع XML بسيط:

function simplexml_innerXML($node)
{
    $content="";
    foreach($node->children() as $child)
        $content .= $child->asXml();
    return $content;
}

في التعليمات البرمجية، محل $body_content = $el->asXml(); مع $body_content = simplexml_innerXML($el);

ومع ذلك، يمكن أيضا أن التحول إلى API آخر العروض التمييز بين innerXML (ما كنت تبحث عن) وouterXML (ما تحصل عليه في الوقت الحالي). مايكروسوفت دوم العروض libary هذا التمييز ولكن للأسف PHP DOM لا.

ولقد وجدت أن PHP XMLReader API يوفر هذا distintion. انظر readInnerXML (). على الرغم من هذا API لا بأس به مقاربة مختلفة لمعالجة XML. تحاول ذلك.

وأخيرا، أود أن أؤكد ليس المقصود أن XML لاستخراج البيانات والأشجار الفرعية بل كقيمة. هذا هو السبب الذي يركض داخل صعوبة في العثور على API الصحيح. فإنه سيكون أكثر "قياسي" لالشجرة الفرعية متجر HTML كقيمة (ونجاة من جميع العلامات) بدلا من الشجرة الفرعية XML. أيضا حذار أن بعض synthax HTML ليست دائما XML متوافق (أي
مقابل،
). على أي حال في الواقع، كنت نهج هو بالتأكيد أكثر ملاءمة لتحرير ملف xml.

وأود أن يكون توسيع الطبقة SimpleXmlElement:

class MyXmlElement extends SimpleXMLElement{

    final public function innerXML(){
        $tag = $this->getName();
        $value = $this->__toString();
        if('' === $value){
            return null;
        }
        return preg_replace('!<'. $tag .'(?:[^>]*)>(.*)</'. $tag .'>!Ums', '$1', $this->asXml());
    }
}

ومن ثم استخدامها مثل هذا:

echo $qa->answer->innerXML();
<?php
    function getInnerXml($xml_text) {           
        //strip the first element
        //check if the strip tag is empty also
        $xml_text = trim($xml_text);
        $s1 = strpos($xml_text,">");        
        $s2 = trim(substr($xml_text,0,$s1)); //get the head with ">" and trim (note that string is indexed from 0)

        if ($s2[strlen($s2)-1]=="/") //tag is empty
            return "";

        $s3 = strrpos($xml_text,"<"); //get last closing "<"        
        return substr($xml_text,$s1+1,$s3-$s1-1);
    }

    var_dump(getInnerXml("<xml />"));
    var_dump(getInnerXml("<xml  /  >faf <  / xml>"));
    var_dump(getInnerXml("<xml      ><  / xml>"));    
    var_dump(getInnerXml("<xml>faf <  / xml>"));
    var_dump(getInnerXml("<xml  >  faf <  / xml>"));      
?>

وبعد أن بحث لبعض الوقت، حصلت على أي حل يرضي. لذلك كتبت وظيفة بلدي. سوف تحصل على هذه الوظيفة بالضبط محتوى innerXml (بما في ذلك الأبيض في الفضاء، وبطبيعة الحال). لاستخدامها، لتمرير نتيجة asXML() وظيفة، مثل هذا getInnerXml($e->asXML()). هذا العمل وظيفة لعناصر مع العديد من البادئات وكذلك (كما حالتي، وأنا لا يمكن العثور على أي الأساليب الحالية التي لا التحويل على كل عقدة الطفل من البادئات مختلفة).

وإخراج:

string '' (length=0)    
string '' (length=0)    
string '' (length=0)    
string 'faf ' (length=4)    
string '  faf ' (length=6)
    function get_inner_xml(SimpleXMLElement $SimpleXMLElement)
    {
        $element_name = $SimpleXMLElement->getName();
        $inner_xml = $SimpleXMLElement->asXML();
        $inner_xml = str_replace('<'.$element_name.'>', '', $inner_xml);
        $inner_xml = str_replace('</'.$element_name.'>', '', $inner_xml);
        $inner_xml = trim($inner_xml);
        return $inner_xml;
    }

إذا كنت لا تريد لتجريد قسم CDATA، تعليق خارج خطوط 6-8.

function innerXML($i){
    $text=$i->asXML();
    $sp=strpos($text,">");
    $ep=strrpos($text,"<");
    $text=trim(($sp!==false && $sp<=$ep)?substr($text,$sp+1,$ep-$sp-1):'');
    $sp=strpos($text,'<![CDATA[');
    $ep=strrpos($text,"]]>");
    $text=trim(($sp==0 && $ep==strlen($text)-3)?substr($text,$sp+9,-3):$text);
    return($text);
}

ويمكنك فقط استخدام هذه الدالة:)

function innerXML( $node )
{
    $name = $node->getName();
    return preg_replace( '/((<'.$name.'[^>]*>)|(<\/'.$name.'>))/UD', "", $node->asXML() );
}

واستخدام التعابير المنطقية يمكن أن تفعله هذه

preg_match(’/<answer(.*)?>(.*)?<\/answer>/’, $xml, $match);
$result=$match[0];
print_r($result);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top