Soru PHP'de XML belgesi oluşturma (kaçış karakterleri)


Bir PHP betiğinden bir XML belgesi oluşturuyorum ve XML özel karakterlerinden kurtulmam gerekiyor. Kaçması gereken karakterlerin listesini biliyorum; ama bunu yapmanın doğru yolu nedir?

Karakterler sadece ters eğik çizgi (\ ') ile kaçtıysa veya uygun yol nedir? Bunu benim için halledebilecek yerleşik bir PHP işlevi var mı?


45
2017-10-18 07:53


Menşei


@Tchalvak: Kefalet açıklamanızda eleştirdiğiniz puanların çoğunda yanılıyorsunuz. Bunu mevcut cevaplarla görünmeye çalıştım, umarım bu yardımcı olur. - hakre
Dize kaçan için DOM API'yi kullanmak için cevabımda önermedim. Bu API'yi kullanarak tüm XML belgenizi oluşturmanızı önerdim. Bu, ödül açıklamanızda bahsettiğiniz sorunlara yanıttır. - Ionuț G. Stan


Cevaplar:


Kullan DOM Tüm XML belgenizi oluşturmaya yönelik sınıflar. Dikkat çekmek istemediğimiz kodlamaları ve kodlamaları ele alacaktır.


Düzenle: Bu @Tchalvak tarafından eleştirildi:

DOM nesnesi tam bir XML belgesi yaratır, kendi başına bir dizgiyi kodlamak için kendisini kolayca yatırmaz.

Yanlış olan DOMDocument, belgenin tamamını değil, yalnızca bir parçayı doğru bir şekilde verebilir:

$doc->saveXML($fragment);

hangi verir:

Test &amp; <b> and encode </b> :)
Test &amp;amp; &lt;b&gt; and encode &lt;/b&gt; :)

de olduğu gibi:

$doc = new DOMDocument();
$fragment = $doc->createDocumentFragment();

// adding XML verbatim:
$xml = "Test &amp; <b> and encode </b> :)\n";
$fragment->appendXML($xml);

// adding text:
$text = $xml;
$fragment->appendChild($doc->createTextNode($text));

// output the result
echo $doc->saveXML($fragment);

Görmek gösteri


33
2017-10-18 08:00



Göre bugs.php.net/bug.php?id=31191 özellikle kullanmak istiyorsun createTextNode Doğru otomatik kaçış elde etmek için işlev. - Jonathan
Sanırım @Tchalvak meselesi, onun akışı temelli değil. Bu DOM kullanarak bir grup nesne yaratacaktır. Bahsettiğim gibi Cevap XMLWriter'i kullanabilir veya Java kodumu uygun çıkış yapan PHP'ye yönlendirebilir (Tomas Jancik yolu doğru değildir). - Adam Gent
, Whoops eval.in/10980 doğru bir şekilde uygulanmasıdır xmlentities() yerel işlemeyi kullanan işlev. Muhtemelen bazı ek yükleri vardır, ancak o zaman, muhtemelen yerli / geleceğe dönük bir işlevsellik kullanmanın rahatlığına değer. - Kzqai
Bu, dom nesnesini kullanarak çift veya tek tırnak işareti ile uğraşmıyor görünmektedir: eval.in/11043 - Kzqai
@Pete: Tek hat çözümünü kullanarak bitti. Å => & aring gibi şeyleri şifrelemesi dışında harika çalışır; ve ø => & oslash; kodlanmamış bırakılmaları güvenli olsa bile. Bunu aşmak için, karakter kümesini belirtmem ve saveHtml yerine saveXml kullanmam gerekiyordu. new DOMDocument('1.0', 'utf-8'))->appendChild(new DOMText($value))->parentNode->saveXml(). Not: Senin yorumunun muhtemelen kendi cevabı olmalı. - Eric Seastrand


İle kaçan basit bir işlev oluşturdum beş "önceden tanımlanmış varlık" XML'de olanlar:

function xml_entities($string) {
    return strtr(
        $string, 
        array(
            "<" => "&lt;",
            ">" => "&gt;",
            '"' => "&quot;",
            "'" => "&apos;",
            "&" => "&amp;",
        )
    );
}

Kullanım örneği gösteri:

$text = "Test &amp; <b> and encode </b> :)";
echo xml_entities($text);

Çıktı:

Test &amp;amp; &lt;b&gt; and encode &lt;/b&gt; :)

Benzer bir etki kullanılarak elde edilebilir str_replace ancak çift değiştirme nedeniyle kırılgandır (test edilmemiş, tavsiye edilmez):

function xml_entities($string) {
    return str_replace(
        array("&",     "<",    ">",    '"',      "'"),
        array("&amp;", "&lt;", "&gt;", "&quot;", "&apos;"), 
        $string
    );
}

35
2017-10-18 08:26



Taşıman gerek "&" ve "&amp;" dizi öğeleri başlangıçta veya oluşturulmuş tüm diğer varlıkları da değiştirip değiştireceklerdir. Ayrıca strtr Çözüm hiç işe yaramıyor. - Ry-♦
5 xml varlıklar? Keşke o kadar basit olsaydı... - NDM
OP kendi sorusuna cevap vermek için burada gerçekten ciddi kusurlar vardı. İyi için düzenlemeye çalıştım, ama orijinal kodun kullanılmış olup olmadığını merak ediyorum;) - @Nicky De Maeyer: Evet, XML'de önceden tanımlanmış beş varlık var, bir bağlantı verdim. - hakre
Evet ama özellik kaçınıyor farklı kaçan eleman (yani bir özniteliğe koyduğunuz içerikler). Örnek için Java koduma bakın. @TomasJancik'in ne yaptığını yapmak istemezsin. Lütfen yapma!. Bir kütüphane kullanın ya da doğru yapın. - Adam Gent


Ne hakkında htmlspecialchars() işlev?

htmlspecialchars($input, ENT_QUOTES | ENT_XML1, $encoding);

Not:   ENT_XML1 bayrak sadece PHP 5.4.0 veya daha üst sürümlere sahipseniz kullanılabilir.

htmlspecialchars() Bu parametreler ile aşağıdaki karakterlerin yerini alır:

  • & (ve işareti) olur &amp;
  • " (çift tırnak) olur &quot;
  • ' (tek tırnak) olur &apos;
  • < (daha az) olur &lt;
  • > (büyüktür) olur &gt;

Çeviri tablosunu kullanarak get_html_translation_table() işlevi.


16
2018-02-15 07:46



Özel bir ihtiyaç yoktur ENT_XML1 XML uyumlu kodlama için - en azından PHP sürümleri 4.3.0 ila 5.5.0alpha4 için. Basit htmlspecialchars($input, ENT_QUOTES, $encoding); Adlandırılmış bir varlık yerine bir sayısal ile yaşayabiliyorsanız iş de yapar. - hakre


XML varlık sorunu ile uğraşmak için çok uğraştım, bu şekilde çözmek:

htmlspecialchars($value, ENT_QUOTES, 'UTF-8')

12
2017-08-04 22:04



Bu yalnızca bu varlıklar XML'de tanımlanmışsa çalışır, bkz. w3.org/TR/xml-entity-names - hakre


Geçerli bir son XML metnine sahip olmanız için, tüm XML varlıklarından kurtulmanız ve XML belge işleme-talimatı ile aynı kodlamayla yazılmış metni yazmanız gerekir. <?xml hat). Vurgulu karakterlerin, belge olarak kodlandıkları sürece kaçmaları gerekmez.

Ancak, birçok durumda girişi htmlspecialchars çift ​​kodlu varlıklar oluşturabilir (örneğin &eacute; olacaktı &amp;eacute;), bu yüzden önce html varlıkları çözmeyi öneririm:

function xml_escape($s)
{
    $s = html_entity_decode($s, ENT_QUOTES, 'UTF-8');
    $s = htmlspecialchars($s, ENT_QUOTES, 'UTF-8', false);
    return $s;
}

Artık, tüm aksanlı karakterlerin XML belgesi kodlamasında geçerli olduğundan emin olmanız gerekir. Tüm XML ayrıştırıcılarının XML belge işleme-talimatı kodlamasına uymadığından, XML çıktısını her zaman UTF-8'de kodlamayı şiddetle öneririm. Girişiniz farklı bir karakter kümesinden gelebilirse kullanmayı deneyin. utf8_encode().

Girişiniz bu kodlamalardan birinden gelebilecek özel bir durum var: ISO-8859-1, ISO-8859-15, UTF-8, cp866, cp1251, cp1252 ve KOI8-R - PHP bunların hepsini ele alıyor. aynı, ama bazı küçük farklılıklar var - bunlardan bazıları iconv() idare edemez. Bu kodlama sorununu yalnızca tamamlayarak çözebilirim utf8_encode() davranışı:

function encode_utf8($s)
{
    $cp1252_map = array(
    "\xc2\x80" => "\xe2\x82\xac",
    "\xc2\x82" => "\xe2\x80\x9a",
    "\xc2\x83" => "\xc6\x92",
    "\xc2\x84" => "\xe2\x80\x9e",
    "\xc2\x85" => "\xe2\x80\xa6",
    "\xc2\x86" => "\xe2\x80\xa0",
    "\xc2\x87" => "\xe2\x80\xa1",
    "\xc2\x88" => "\xcb\x86",
    "\xc2\x89" => "\xe2\x80\xb0",
    "\xc2\x8a" => "\xc5\xa0",
    "\xc2\x8b" => "\xe2\x80\xb9",
    "\xc2\x8c" => "\xc5\x92",
    "\xc2\x8e" => "\xc5\xbd",
    "\xc2\x91" => "\xe2\x80\x98",
    "\xc2\x92" => "\xe2\x80\x99",
    "\xc2\x93" => "\xe2\x80\x9c",
    "\xc2\x94" => "\xe2\x80\x9d",
    "\xc2\x95" => "\xe2\x80\xa2",
    "\xc2\x96" => "\xe2\x80\x93",
    "\xc2\x97" => "\xe2\x80\x94",
    "\xc2\x98" => "\xcb\x9c",
    "\xc2\x99" => "\xe2\x84\xa2",
    "\xc2\x9a" => "\xc5\xa1",
    "\xc2\x9b" => "\xe2\x80\xba",
    "\xc2\x9c" => "\xc5\x93",
    "\xc2\x9e" => "\xc5\xbe",
    "\xc2\x9f" => "\xc5\xb8"
    );
    $s=strtr(utf8_encode($s), $cp1252_map);
    return $s;
}

5
2018-02-21 15:57





Doğru xml çıktısına ihtiyacınız varsa, simpleksml gitmenin yoludur:

http://www.php.net/manual/en/simplexmlelement.asxml.php


2
2018-02-21 16:42





Doğru kaçış doğru XML çıktısını almanın yoludur, ancak kaçış işlemine devam etmelisiniz farklı olarak için Öznitellikler ve elementler. (Tomas'ın cevabı yanlıştır).

Biraz yazdım / çaldım Java kodu Bir süre sonra öznitelik ve öğe kaçması arasında ayrım yapar. Bunun nedeni, XML ayrıştırıcısının tüm beyaz alanı özellikle özelliklerde özel olarak ele almasıdır.

PHP'ye giden limana önem verilmelidir (Tomas Jancik'in yukarıdaki uygun kaçış ile yaklaşımını kullanabilirsiniz). Kullanıyorsanız, genişletilmiş varlıklar kaçmak için endişelenmenize gerek yok UTF-8.

Java kodumu kullanmak istemiyorsanız, XMLWriter akış tabanlı ve libxml kullanır bu yüzden çok verimli olması gerekir.


1
2018-02-21 19:09



+1 Çünkü XMLWriter'in sizin için otomatik olarak yaptığını hiç bilmiyordum. - Shackrock


Bu yöntemleri kullanabilirsiniz: http://php.net/manual/en/function.htmlentities.php

Bu şekilde, tüm varlıklar (html / xml) kaçtı ve dizenizi XML etiketlerine yerleştirebilirsiniz.


0
2017-10-18 07:59



Bu, HTML öğelerinin XML varlıklarından daha büyük bir kümedir ve çoğu XML ayrıştırıcısı, XML öğeleri listesinde bulunmayan birçok HTML öğesi tanımamadığından, bu kötü bir çözümdür. - Sharique Abdullah