Arkasında Olumsuz Bakış PHP kullanarak Düzenli ifadeler ile Yardım

4 Cevap php

Ben PHP preg_replace kullanarak eksik HTML etiketleri kapatmak için basit bir fonksiyon yazmaya çalışıyorum.

Ben nispeten düz ileri olacağını düşündüm, ama nedense o olmamıştır.

Ne temelde yapmaya çalışıyorum aşağıdaki satırda yakın bir eksik etiketi:

<tr>
<th class="ProfileIndent0">
<p>Global pharmaceuticals</p>
<td>197.2</td>
<td>94</td>
</tr>

Attığım oldum yaklaşım açıldı inci ve düzgün kapalı inci etiketleri önünde değildir td etiketleri açılış bulmak için arkasında bir negatif görünüm kullanmaktır.

Örneğin:

$text = preg_replace('!<th(\s\S*){0,1}?>(.*)((?<!<\/th>)[\s]*<td>)!U','<th$1>$2</th>',$text);

Ben boşuna düzenli ifade deseni sayısız farklı şekillerde yazdım. Ancak yerine açık td etiketleri birkaç on maç gibi görünüyor - Sorun maddenin kutuyu inci / eksik olan sadece bir açık td üzerinde maç değildi ki olmuştur.

İşte tam giriş metin bulunuyor:

<CO_TEXT text_type_id="6">
        <TEXT_DATA><![CDATA[<table class="ProfileChart"> <tr> <th class="TableHead" colspan="21">2008 Sales</th> </tr>

<tr> <th class="ProfileIndent0"></th> <th class="ProfileHead">$ mil.</th> <th class="ProfileHead">% of total</th> </tr>

<tr> <th class="ProfileIndent0"> <p>Global pharmaceuticals</p> <td>197.2</td> <td>94</td> </tr>

<tr> <th class="ProfileIndent0">Impax pharmaceuticals</th> <td>12.9</td> <td>6</td> </tr>

<tr> <th class="ProfileTotal">Total</th> <td class="ProfileDataTotal">210.1</td> <td class="ProfileDataTotal">100</td> </tr> </table><h3>Selected Generic Products</h3><ul class="prodoplist"><li>Anagrelide hydrochloride (generic Agrylin, thrombocytosis)</li><li>Bupropion hydr ochloride (generic Wellbutrin SR, depression)</li><li>Colestipol hydrochloride (generic Colestid, high cholesterol)</li><li>Dantrolene sodium (generic  Dantrium, spasticity)</li><li>Metformin Hcl (generic Glucophage XR, diabetes)</li><li>Nadolol/Bendroflumethiazide (generic Corzide, hypertension)</li
><li>Oxybutynin chloride (generic Ditropan XL, urinary incontinence, with Teva)</li><li>Oxycodone hydrochloride (generic OxyContin controlled release,  pain)</li><li>Pilocarpine hydrochlorine (generic Salagen, dry mouth caused by radiation therapy)</li></ul>]]></TEXT_DATA> </CO_TEXT>

Ben farkında değilim, ya da sadece sağ eşleşen desen vurmak değil ki PHP negatif görünüm behinds ile olacak bir şey var mı?

Herhangi bir yardım çok takdir.

Thanks, John

4 Cevap

Sorunuzun benim yorum yazma, ben "kesinlikle korumak imkansız hale gelecektir regex çeşit içermeyen başka bir çözüm orada var" düşünüyordum ...

Belki bir yolunu buldum; bakmak

Birincisi devletlerin (alıntı) manuel:

Unlike loading XML, HTML does not have to be well-formed to load.

Ve ikincisi manuel diyor ki:

Creates an HTML document from the DOM representation.


Trying those with the non-valid-HTML string you provided gives this example :

$str = <<<STRING
<tr>
<th class="ProfileIndent0">
<p>Global pharmaceuticals</p>
<td>197.2</td>
<td>94</td>
</tr>
STRING;

$doc = new DOMDocument();
$doc->loadHTML($str);
echo $doc->saveHTML();

Ve bunu çalıştırırken (from the command-line, to avoid any trouble with escaping HTML to get it displayed properly), alıyorum:

$ php ./temp.php
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><tr>
<th class="ProfileIndent0">
<p>Global pharmaceuticals</p>
</th>
<td>197.2</td>
<td>94</td>
</tr></body></html>

Hangi, yeniden biçimlendirilmiş verir:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" 
    "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
    <body>
        <tr>
            <th class="ProfileIndent0">
                <p>Global pharmaceuticals</p>
            </th>
            <td>197.2</td>
            <td>94</td>
        </tr>
    </body>
</html>

Mükemmel değil ama, ben ), örneğin, (it did not add any <table> etiketleri itiraf, ama, en azından, etiketleri şimdi gerektiği gibi kapalı ...

DOCTYPE ve <html> etiketleri ile bazı sorunlar olabilir; bu ... some comments manuel sayfasında bir göz atın istemeyebilirsiniz: onlar size yardımcı olabilir ;-)



Biraz daha düşündükten sonra EDIT:

Sizin "tam" bir örnek bazı uyarılar üretir; belki biraz loadHTML ot besleme önce "HTML" derli toplu olabilir ...

Warning: DOMDocument::loadHTML(): Tag co_text invalid in Entity, 
    line: 1 in /home/squale/developpement/tests/temp/temp.php on line 18
Warning: DOMDocument::loadHTML(): Tag text_data invalid in Entity, 
    line: 2 in /home/squale/developpement/tests/temp/temp.php on line 18
Warning: DOMDocument::loadHTML(): htmlParseStartTag: invalid element name in Entity, 
    line: 2 in /home/squale/developpement/tests/temp/temp.php on line 18
Warning: DOMDocument::loadHTML(): Unexpected end tag : table in Entity, 
    line: 10 in /home/squale/developpement/tests/temp/temp.php on line 18

At worse, you could mask those errors, either by using the error_reporting function before and after calling the function, or using the @ operator...
I wouldn't generally recommend those, however : using those should be in extreme cases -- maybe this one ^^

Yine de, sonuç aslında kötü bakmıyor:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" 
    "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<body>
    <co_text text_type_id="6">
        <text_data>
            <tr>
                <th class="TableHead" colspan="21">2008 Sales</th> 
            </tr>
            <tr>
                <th class="ProfileIndent0"></th> 
                <th class="ProfileHead">$ mil.</th> 
                <th class="ProfileHead">% of total</th> 
            </tr>
            <tr>
                <th class="ProfileIndent0"> <p>Global pharmaceuticals</p> </th>
                <td>197.2</td> 
                <td>94</td> 
            </tr>
            <tr>
                <th class="ProfileIndent0">Impax pharmaceuticals</th> 
                <td>12.9</td> 
                <td>6</td> 
            </tr>
            <tr>
                <th class="ProfileTotal">Total</th> 
                <td class="ProfileDataTotal">210.1</td> 
                <td class="ProfileDataTotal">100</td> 
            </tr>
            <h3>Selected Generic Products</h3>
            <ul class="prodoplist">
                <li>Anagrelide hydrochloride (generic Agrylin, thrombocytosis)</li>
                <li>Bupropion hydr ochloride (generic Wellbutrin SR, depression)</li>
                <li>Colestipol hydrochloride (generic Colestid, high cholesterol)</li>
                <li>Dantrolene sodium (generic  Dantrium, spasticity)</li>
                <li>Metformin Hcl (generic Glucophage XR, diabetes)</li>
                <li>Nadolol/Bendroflumethiazide (generic Corzide, hypertension)</li>
                <li>Oxybutynin chloride (generic Ditropan XL, urinary incontinence, with Teva)</li>
                <li>Oxycodone hydrochloride (generic OxyContin controlled release,  pain)</li>
                <li>Pilocarpine hydrochlorine (generic Salagen, dry mouth caused by radiation therapy)</li>
            </ul>
        ]]&gt;
        </text_data>
    </co_text>
</body>
</html>


To conclude, as others already suggested, a real HTML tidyier/purifier might be able to help ;-)

Ayrıca HTMLTidy veya HTML Purifier otomatik HTML düzeltmek gibi bir şey kullanmak mümkün olabilir.

Ancak yerine açık td etiketleri birkaç on maç gibi görünüyor - Sorun </th> maddenin kutuyu eksik sadece bir açık td üzerinde maç değildi ki olmuştur.

Eğer 'açgözlü olmayan' veya 'tembel' maç ifadeleri istediğiniz gibi geliyor. '*?' ve '+?' yerine '*' ve '+' kullanımı, ve bir maç olsun gibi birkaç karakteri olabildiğince kapmak yerine edecek o kadar çok daha.

Bu regex benim için çalışıyor:

$text = preg_replace('@<th([^>]*)>(.*<\/td>)(<\/th>)?@','<th$1>$2</th>',$text);

Sadece tek satır satır için çalıştığını unutmayın. Ben bunun için çalışmak, ortalama:

<tr><th><td>some</td></tr>

ancak için:

<tr><th>
<td>some</td>
</tr>

Ben gerçekten "s" değiştirici ile çalışmak nasıl bilmiyorum. Birisi bana açıklayabilir sevinirim.

İşte benim örnek:

<?php
$html = '<CO_TEXT text_type_id="6">
        <TEXT_DATA><![CDATA[<table class="ProfileChart"> <tr> <th class="TableHead" colspan="21">2008 Sales</th> </tr>

<tr> <th class="ProfileIndent0"></th> <th class="ProfileHead">$ mil.</th> <th class="ProfileHead">% of total</th> </tr>

<tr> <th class="ProfileIndent0"> <p>Global pharmaceuticals</p> <td>197.2</td> <td>94</td> </tr>

<tr> <th class="ProfileIndent0">Impax pharmaceuticals</th> <td>12.9</td> <td>6</td> </tr>

<tr> <th class="ProfileTotal">Total</th> <td class="ProfileDataTotal">210.1</td> <td class="ProfileDataTotal">100</td> </tr> </table><h3>Selected Generic Products</h3><ul class="prodoplist"><li>Anagrelide hydrochloride (generic Agrylin, thrombocytosis)</li><li>Bupropion hydr ochloride (generic Wellbutrin SR, depression)</li><li>Colestipol hydrochloride (generic Colestid, high cholesterol)</li><li>Dantrolene sodium (generic  Dantrium, spasticity)</li><li>Metformin Hcl (generic Glucophage XR, diabetes)</li><li>Nadolol/Bendroflumethiazide (generic Corzide, hypertension)</li
><li>Oxybutynin chloride (generic Ditropan XL, urinary incontinence, with Teva)</li><li>Oxycodone hydrochloride (generic OxyContin controlled release,  pain)</li><li>Pilocarpine hydrochlorine (generic Salagen, dry mouth caused by radiation therapy)</li></ul>]]></TEXT_DATA> </CO_TEXT>';

$text = preg_replace('@<th([^>]*)>(.*<\/td>)(<\/th>)?@s','<th$1>$2</th>',$html);
echo $text;
?>

çıktı:

<CO_TEXT text_type_id="6">
        <TEXT_DATA><![CDATA[<table class="ProfileChart"> <tr> <th class="TableHead" colspan="21">2008 Sales</th> </tr>

<tr> <th class="ProfileIndent0"></th> <th class="ProfileHead">$ mil.</th> <th class="ProfileHead">% of total</th> </tr>

<tr> <th class="ProfileIndent0"> <p>Global pharmaceuticals</p> <td>197.2</td> <td>94</td> </tr>

<tr> <th class="ProfileIndent0">Impax pharmaceuticals</th> <td>12.9</td> <td>6</td> </tr>

<tr> <th class="ProfileTotal">Total</th> <td class="ProfileDataTotal">210.1</td> <td class="ProfileDataTotal">100</td></th> </tr> </table><h3>Selected Generic Products</h3><ul class="prodoplist"><li>Anagrelide hydrochloride (generic Agrylin, thrombocytosis)</li><li>Bupropion hydr ochloride (generic Wellbutrin SR, depression)</li><li>Colestipol hydrochloride (generic Colestid, high cholesterol)</li><li>Dantrolene sodium (generic  Dantrium, spasticity)</li><li>Metformin Hcl (generic Glucophage XR, diabetes)</li><li>Nadolol/Bendroflumethiazide (generic Corzide, hypertension)</li
><li>Oxybutynin chloride (generic Ditropan XL, urinary incontinence, with Teva)</li><li>Oxycodone hydrochloride (generic OxyContin controlled release,  pain)</li><li>Pilocarpine hydrochlorine (generic Salagen, dry mouth caused by radiation therapy)</li></ul>]]></TEXT_DATA> </CO_TEXT>