2013-03-21 4 views
9

मैं सभी रूट-लेवल # टेक्स्ट नोड्स (या div माता-पिता वाले) को ढूंढना चाहता हूं जिन्हें <p> टैग के अंदर लपेटा जाना चाहिए। निम्नलिखित पाठ में तीन (या यहां तक ​​कि केवल दो) अंतिम रूट <p> टैग होना चाहिए।डीओएम xpath #text नोड्स को ढूंढने और अनुच्छेद टैग में लपेटें

<div> 
    This text should be wrapped in a p tag. 
</div> 

This also should be wrapped. 

<b>And</b> this. 

विचार टेक्स्ट निसर को प्रारूपित करना है ताकि टेक्स्ट ब्लॉक HTML प्रदर्शन के लिए पैराग्राफ में समूहीकृत हो जाएं। हालांकि, निम्न xpath मैं काम कर रहा हूं लगता है कि पाठ नोड्स का चयन करने में विफल रहता है।

<?php 

$html = '<div> 
    This text should be wrapped in a p tag. 
</div> 

This also should be wrapped. 

<b>And</b> this.'; 

libxml_use_internal_errors(TRUE); 

$dom = DOMDocument::loadHTML($html); 

$xp = new DOMXPath($dom); 

$xpath = '//text()[not(parent::p) and normalize-space()]'; 

foreach($xp->query($xpath) as $node) { 
    $element = $dom->createElement('p'); 
    $node->parentNode->replaceChild($element, $node); 
    $element->appendChild($node); 
} 

print $dom->saveHTML(); 
+3

आपने अपने XPath अभिव्यक्ति में '// div' क्यों रखा है यदि आप 'div' के बाहर टेक्स्ट नोड्स भी चुनना चाहते हैं? [यह बेवकूफ] (http://codepad.org/hzOefCsH) ऐसा लगता है जो आप चाहते हैं। – nwellnhof

+0

क्या आप मुझे बता सकते हैं कि मैंने ऊपर दिए गए समाधान के साथ क्या गलत है? क्या आप न्यूलाइन के साथ टेक्स्ट को कई अनुच्छेदों में कनवर्ट करना चाहते हैं? – nwellnhof

+0

@nwellnhof, आपका समाधान ठीक है - लेकिन यह कोई जवाब नहीं है इसलिए मैं आपको कुछ भी नहीं दे सकता। – Xeoncross

उत्तर

5

ठीक है, तो मुझे एक उत्तर के रूप में मेरी टिप्पणी दोबारा दोहराएं। यदि आप सभी टेक्स्ट नोड्स से मेल खाना चाहते हैं, तो आपको अपने XPath अभिव्यक्ति से //div भाग को हटा देना चाहिए। तो यह हो जाता है:

//text()[not(parent::p) and normalize-space()] 
+0

यह '

this text is ok
के साथ कैसे काम करेगा? लेकिन इस के बारे में कैसे?' '? – mzedeler

1

आप इसे शुद्ध जावास्क्रिप्ट के साथ क्या कर सकते हैं यदि आप चाहें तो:

var content = document.evaluate(
             '//text()', 
             document, 
             null, 
             XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, 
             null); 

for (var i=0 ; i < content .snapshotLength; i++){ 
    console.log(content .snapshotItem(i).textContent); 
} 
2

आपका परिदृश्य कई किनारे मामलों और शब्द चाहिए शीर्ष पर जोड़ रहा है है। मुझे लगता है कि आप क्लासिक करना चाहते हैं, एक डबल ब्रेक एक नया अनुच्छेद चीज शुरू करता है, हालांकि इस बार माता-पिता <div> (या निश्चित रूप से अन्य ब्लॉक तत्व) के भीतर भी।

मैं एचटीएमएल पार्सर को अधिकांश काम करने देता हूं लेकिन मैं अभी भी टेक्स्ट सर्च के साथ काम करता हूं और प्रतिस्थापित करता हूं (xpath के बगल में)। तो आप जो कुछ देखेंगे वह थोड़ा हैकिश है लेकिन मुझे लगता है कि बहुत स्थिर है:

सबसे पहले मैं सभी टेक्स्ट-नोड्स का चयन करूंगा जो शीर्ष स्तर के या निम्न div के बच्चे हैं।

(.|./div)/text() 

यह xpath एक लंगर तत्व है जो <body> टैग है जब DOMDocument में लोड के रूप में यह अपने HTML टुकड़ा की जड़-टैग का प्रतिनिधित्व करता है के सापेक्ष है।

यदि एक div के बच्चे तो मैं शुरुआत में शुरुआती पैराग्राफ डाल दूंगा।

फिर किसी भी मामले में मैं एक अनुक्रम की प्रत्येक घटना पर एक ब्रेक-मार्क (यहां टिप्पणी के रूप में) डालता हूं जो एक नया पैराग्राफ शुरू करता है (जो "\n\n" होना चाहिए क्योंकि व्हाइटसाइट सामान्यीकरण के कारण, मैं गलत हो सकता हूं और यदि यह लागू नहीं होता है, आपको यह काम पारदर्शी रूप से करने के लिए व्हाइटसाइट-सामान्यीकरण को आगे बढ़ाने की आवश्यकता होगी)।

/* @var $result DOMText[] */ 
$result = $xp->query('(.|./div)/text()', $anchor); 

foreach ($result as $i => $node) 
{ 
    if ($node->parentNode->tagName == 'div') 
    { 
     $insertBreakMarkBefore($node, true); 
    } 

    while (FALSE !== $pos = strpos($node->data, $paragraphSequence)) 
    { 
     $node = $node->splitText($pos + $paragraphSequenceLength); 
     $insertBreakMarkBefore($node); 
    } 
} 

इन डाला तोड़ने के निशान अभी देखते हैं एक HTML <p> टैग के साथ बदला जाएगा। एक HTML पार्सर उन्हें <p>...</p> जोड़े में बदल देगा ताकि मैं खुद को उस एल्गोरिदम लिख सकूं (भले ही यह दिलचस्प हो)। यह मूल रूप से काम की तरह मैं एक बार कुछ अन्य जवाब में बताया गया है, लेकिन मैं सिर्फ लिंक किसी भी अब नहीं मिल रहा है:

  1. डोम पेड़ के संशोधन के बाद, फिर से <body> की innter एचटीएमएल मिलता है।
  2. "<p>" साथ सेट अंक बदलें (यहाँ मैं वर्ग के रूप में अच्छी तरह से निशान इस दृश्यमान बनाने के लिए) उचित <p>...</p> जोड़े के साथ डोम फिर से बनाने के लिए फिर से पार्सर में HTML टुकड़ा
  3. लोड।
  4. एचटीएमएल को फिर से DOMDocument पार्सर से प्राप्त करें, जो अब अंत में है।

कोड में इन उल्लिखित चरणों (एक पल के लिए समारोह परिभाषा के कुछ लंघन):

$needle = sprintf('%1$s<!--%2$s-->%1$s', $paragraphSequence, $paragraphComment); 
$replace = sprintf("\n<p class=\"%s\">\n", $paragraphComment); 
$html = strtr($innerHTML($anchor), array($needle . $needle => $replace, $needle => $replace)); 

echo "HTML afterwards:\n", $innerHTML($loadHTMLFragment($html)); 

इस शो के रूप में, डबल दृश्यों को एक साथ बदल दिए जाते हैं। शायद अंत में एक को भी हटाया जाना चाहिए (अगर आवेदक, तो आप यहां व्हाइटस्पेस भी ट्रिम कर सकते हैं)।

अंतिम HTML आउटपुट: अच्छा उत्पादन प्रारूपण के लिए

<div> 
<p class="break"> 

    This text should be wrapped in a p tag. 
</p> 
</div> 
<p class="break"> 
This also should be wrapped. 
</p> 
<p class="break"> 
<b>And</b> this.</p> 

कुछ और बाद के उत्पादन उपयोगी भी हो सकता है। असल में मुझे लगता है कि ऐसा करने के लायक है क्योंकि इससे आपको एल्गोरिदम (Full Demo) को ट्विक करने में मदद मिलेगी - बस देखकर, व्हाइटसाइट सामान्यीकरण शायद वहां लागू नहीं होता है। इसलिए देखभाल के साथ उपयोग करें)।

+0

अच्छा स्पष्टीकरण, हालांकि, आपका डेमो वास्तव में इस परिणाम को प्राप्त नहीं कर रहा है। – Xeoncross

+1

जैसा कि बहुत अंत में लिखा गया है, यह गायब सफेद जगह सामान्यीकरण की वजह से है। सुनिश्चित करें कि इनपुट लाइन \ विभाजक के रूप में '\ n' का उपयोग करता है, कोडपैड' \ r \ n' या कुछ समानता का उपयोग करता है, यही कारण है कि आप इसे अलग देखते हैं। मैं बाद में दोबारा जांच कर सकता हूं, मैंने देखा कि जब मैंने इसे चिपकाया, तो मेरे अपने बॉक्स पर कोड काम करता है। तो अपने लिए प्रयास करें, यह पहले से ही आपके बॉक्स पर काम कर सकता है। – hakre

1

मैं जानता हूँ कि यह xpath नहीं है, लेकिन यह बाहर की जाँच:

पीएचपी सरल HTML डोम पार्सर

http://simplehtmldom.sourceforge.net/

विशेषताएं

एक एचटीएमएल डोम पार्सर PHP5 + में लिखा आप में हेरफेर करते हैं एक बहुत ही आसान तरीके से एचटीएमएल!

अमान्य HTML का समर्थन करता है।

jQuery के समान चयनकर्ताओं के साथ एक HTML पृष्ठ पर टैग खोजें।

एक ही पंक्ति में एचटीएमएल से सामग्री निकालें।

+0

कृपया अपने उत्तर में दिखाएं कि यह पुस्तकालय के साथ कैसे काम करता है, अन्यथा यह केवल आंशिक रूप से संबंधित है (और मेरे व्यक्तिगत स्वाद के लिए, लाइब्रेरी एक बुरा सुझाव है, PHP आजकल सबकुछ निर्मित है-जो पुस्तकालय ऑफ़र करता है, वह * PHP सरल HTML डोम पार्सर * पुस्तकालय मूल रूप से PHP 4 के लिए libxml आधारित एक्सटेंशन के बिना लिखा गया था क्योंकि वे अब तक मौजूद नहीं थे। – hakre

संबंधित मुद्दे