PHP SimpleXML olsun InnerXml

7 Cevap php

Ben bu XML bit answer HTML içeriğini almak gerekir:

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

Yani ", kim , beni " dizesini almak istiyorum.

Ben answer varsa, bir SimpleXMLElement, ben " almak için asXML() çağırabilirsiniz Kim kim, kim ,, bana ", ama kendisi sarılı öğesi olmadan bir elemanın iç XML nasıl?

Ben dize işlevlerini içermeyen yolları tercih, ama bu tek yolu ise, yani o olurdu.

7 Cevap

Bilgime iyi için, bu almak için yerleşik bir yolu yoktur. Ben ortak sorunların çoğu için kolaylık yöntem sunar SimpleXMLElement uzanan bir PHP sınıfı olan, SimpleDOM çalışıyorum tavsiye ederim.

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();

Aksi takdirde, bunu yapmanın iki yolu görüyoruz. Ilk olarak childNodes oluşturmak için XML üzerinde DOMNode daha sonra döngü için SimpleXMLElement dönüştürmek olacaktır. Sonra diğer kök düğümünü kaldırmak için dize işlevlerini kullanın asXML() çağırmak olacaktır. Dikkat rağmen, asXML() bazen outside, XML prolog veya İşleme talimatlar gibi o çağrıldı düğüm, aslında bir biçimlendirme döndürebilir.

(Gerçekten topal görünüyor olsa da) Bu çalışır:

echo (string)$qa->answer;

En basit çözüm, özel basit XML ile InnerXml almak uygulamaktır:

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

Kodunuzda, $body_content = $el->asXml(); $body_content = simplexml_innerXML($el); ile değiştirin

Ancak, aynı zamanda (sizin için ne arıyor) InnerXml ve OuterXml (şimdi için ne olsun) arasında bir ayrım sunan başka bir API geçiş olabilir. Microsoft, Dom kitaplığındaki bu ayrımı sunuyor ama ne yazık ki PHP DOM değil.

Ben PHP XMLReader API, bu distintion sunar bulundu. ReadInnerXML (bkz.). Bu API işleme XML oldukça farklı bir yaklaşım olsa. Deneyin.

Son olarak, XML alt ağaçlar olarak değil değer olarak veri ayıklamak için bir anlamı olmadığını vurgulamak istiyorum. Eğer sorun doğru API bulma içine koşma nedeni budur. Bu bir değer olarak HTML altağaç depolamak (ve tüm etiketleri kaçış) yerine XML alt ağacı daha fazla 'standart' olacak. Ayrıca bazı HTML synthax her zaman XML uyumlu olmadığını sakının (vs ie,
). Neyse uygulamada, size yaklaşım kesinlikle xml dosyasını düzenlemek için daha uygundur.

Ben SimpleXMLElement sınıfını genişletmek olurdu:

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());
    }
}

ve sonra bu gibi kullanabilirsiniz:

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>"));      
?>

After I search for a while, I got no satisfy solution. So I wrote my own function. This function will get exact the innerXml content (including white-space, of course). To use it, pass the result of the function asXML(), like this getInnerXml($e->asXML()). This function work for elements with many prefixes as well (as my case, as I could not find any current methods that do conversion on all child node of different prefixes).

Çıktı:

string '' (length=0)    
string '' (length=0)    
string '' (length=0)    
string 'faf ' (length=4)    
string '  faf ' (length=6)

Eğer CDATA bölümü şerit istemiyorsanız, çizgiler, 6-8 açıklama.

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);
}

regex kullanarak bunu yapabilirsiniz

preg_match(’/<answer(.*)?>(.*)?<\/answer>/’, $xml, $match);
$result=$match[0];
print_r($result);