जेएस के साथ एक HTML स्ट्रिंग पार्स करें


258

मैंने एक समाधान के लिए खोज की लेकिन कुछ भी प्रासंगिक नहीं था, इसलिए यहां मेरी समस्या है:

मैं एक स्ट्रिंग को पार्स करना चाहता हूं जिसमें HTML टेक्स्ट है। मैं इसे जावास्क्रिप्ट में करना चाहता हूं।

मैंने इस लाइब्रेरी की कोशिश की, लेकिन ऐसा लगता है कि यह मेरे वर्तमान पृष्ठ के HTML को एक स्ट्रिंग से नहीं, पार्स करता है। क्योंकि जब मैं नीचे दिए गए कोड को आज़माता हूं, तो यह मेरे पृष्ठ का शीर्षक बदल देता है:

var parser = new HTMLtoDOM("<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>", document);

मेरा लक्ष्य एक HTML बाहरी पृष्ठ से लिंक निकालना है जिसे मैंने एक स्ट्रिंग की तरह पढ़ा है।

क्या आप इसे करने के लिए एक एपीआई जानते हैं?



1
लिंक किए गए डुप्लिकेट पर विधि किसी दिए गए स्ट्रिंग से एक HTML दस्तावेज़ बनाती है। फिर, आप doc.getElementsByTagName('a')लिंक (या यहां तक ​​कि doc.links) को पढ़ने के लिए उपयोग कर सकते हैं ।
रोब डब्ल्यू

यह ध्यान देने योग्य है कि यदि आप React.js जैसे ढांचे का उपयोग कर रहे हैं, तो ऐसा करने के तरीके हो सकते हैं जो फ्रेमवर्क के लिए विशिष्ट हों जैसे: stackoverflow.com/questions/23616226/…
माइक लियोन

क्या इससे आपके सवाल का जवाब मिलता है? टेक्स्ट जावास्क्रिप्ट से HTML स्ट्रिप करें
Leif Arne Storset

जवाबों:


373

डमी डोम तत्व बनाएं और उसमें स्ट्रिंग जोड़ें। फिर, आप इसे किसी भी DOM तत्व की तरह जोड़ तोड़ कर सकते हैं।

var el = document.createElement( 'html' );
el.innerHTML = "<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>";

el.getElementsByTagName( 'a' ); // Live NodeList of your anchor elements

संपादित करें: प्रशंसकों को खुश करने के लिए एक jQuery उत्तर जोड़ना!

var el = $( '<div></div>' );
el.html("<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>");

$('a', el) // All the anchor elements

9
बस एक नोट: इस समाधान के साथ, अगर मैं "अलर्ट (el.innerHTML)" करता हूं, तो मैं <html>, <body> और <head> टैग खो देता हूं ....
स्टेज

2
समस्या: मुझे <फ्रेम> टैग से लिंक प्राप्त करने की आवश्यकता है। लेकिन इस समाधान के साथ, फ्रेम टैग को हटा दिया जाता है ...
चरण

3
@stage मैं एक छोटे से पार्टी के लिए देर से थोड़ा हूँ, लेकिन आप का उपयोग करने के लिए सक्षम होना चाहिए document.createElement('html');संरक्षित करने के लिए <head>और <body>टैग।
सर्वार्थसिद्धि

3
ऐसा लगता है कि आप एक HTML तत्व के भीतर एक HTML तत्व डाल रहे हैं
symbiont

6
मैं चिंतित हूं कि शीर्ष उत्तर के रूप में उत्कीर्ण है। parse()नीचे समाधान अधिक पुन: प्रयोज्य और सुरुचिपूर्ण है।
जस्टिन

232

यह काफी सरल है:

var parser = new DOMParser();
var htmlDoc = parser.parseFromString(txt, 'text/html');
// do whatever you want with htmlDoc.getElementsByTagName('a');

MDN के अनुसार , क्रोम में ऐसा करने के लिए आपको XML की तरह पार्स करने की आवश्यकता है:

var parser = new DOMParser();
var htmlDoc = parser.parseFromString(txt, 'text/xml');
// do whatever you want with htmlDoc.getElementsByTagName('a');

यह वर्तमान में वेबकिट द्वारा असमर्थित है और आपको फ्लोरियन के उत्तर का पालन करना होगा, और यह मोबाइल ब्राउज़रों पर अधिकांश मामलों में काम करने के लिए अज्ञात है।

संपादित करें: अब व्यापक रूप से समर्थित है


35
ध्यान देने योग्य बात यह है कि 2016 में DOMParser अब व्यापक रूप से समर्थित है। caniuse.com/#feat=xml-serializer
aendrew

5
वर्थ यह देखते हुए कि बनाए गए दस्तावेज़ में सभी रिश्तेदार लिंक टूट गए हैं, क्योंकि दस्तावेज़ इनहेरिट करके बनाया जाता documentURLहै window, जो सबसे अधिक संभावना स्ट्रिंग के URL से भिन्न होता है।
छत

2
ध्यान देने योग्य बात यह है कि आपको केवलnew DOMParser एक बार कॉल करना चाहिए और फिर अपनी पूरी स्क्रिप्ट के दौरान उसी ऑब्जेक्ट का पुन: उपयोग करना चाहिए ।
जैक गिफिन

1
parse()नीचे समाधान अधिक पुन: प्रयोज्य और HTML के लिए विशिष्ट है। हालाँकि, यदि आपको XML दस्तावेज़ की आवश्यकता है तो यह अच्छा है।
जस्टिन

मैं इस पार्स किए गए वेबपेज को एक संवाद बॉक्स या कुछ पर कैसे प्रदर्शित कर सकता हूं? मैं उस के लिए समाधान खोजने में सक्षम नहीं था
शारिक मुशर्रफ

18

संपादित करें: HTML, सिर और शरीर हटा दिए जाने के बाद से नीचे का समाधान केवल HTML "टुकड़े" के लिए है। मुझे लगता है कि इस प्रश्न का हल DOMParser का parseFromString () विधि है।


HTML अंशों के लिए, यहां सूचीबद्ध समाधान अधिकांश HTML के लिए काम करता है, हालांकि कुछ मामलों के लिए यह काम नहीं करेगा।

उदाहरण के लिए पार्सिंग का प्रयास करें <td>Test</td>। यह div.innerHTML सॉल्यूशन और न ही DOMParser.prototype.parseFromString और न ही रेंज.क्रिएट कॉन्टेक्शुअल फ़्रेग्मेंट सॉल्यूशन पर काम नहीं करेगा। Td टैग गायब हो जाता है और केवल पाठ रहता है।

केवल jQuery उस मामले को अच्छी तरह से संभालता है।

तो भविष्य का समाधान (MS Edge 13+) टेम्पलेट टैग का उपयोग करना है:

function parseHTML(html) {
    var t = document.createElement('template');
    t.innerHTML = html;
    return t.content.cloneNode(true);
}

var documentFragment = parseHTML('<td>Test</td>');

पुराने ब्राउज़रों के लिए मैंने एक स्वतंत्र gist में jQuery के parseHTML () विधि को निकाला है - https://gist.github.com/Munawwar/6e6362dbdf77c7865a99


यदि आप आगे-संगत कोड लिखना चाहते हैं जो पुराने ब्राउज़रों पर भी काम करता है तो आप टैग को पॉलीफ़िल<template> कर सकते हैं । यह कस्टम तत्वों पर निर्भर करता है जिन्हें आपको पॉलीफिल करने की आवश्यकता हो सकती है । वास्तव में आप बस एक ही समय में webcompords.js को पॉलीफिल कस्टम तत्वों, टेम्प्लेट, शैडो डोम, वादों और कुछ अन्य चीजों का उपयोग करना चाहते हैं।
जेफ लाफलिन ने

12
var doc = new DOMParser().parseFromString(html, "text/html");
var links = doc.querySelectorAll("a");

4
आप उपसर्ग क्यों कर रहे हैं $? इसके अलावा, जैसा कि लिंक किए गए डुप्लिकेट में उल्लेख किया गया है , text/htmlबहुत अच्छी तरह से समर्थित नहीं है, और इसे पॉलीफ़िल का उपयोग करके लागू किया जाना है।
रॉब डब्ल्यू

1
मैंने इस लाइन को एक परियोजना से कॉपी किया है, मैं जावास्क्रिप्ट एप्लिकेशन में $ के साथ उपसर्ग चर का उपयोग कर रहा हूं (पुस्तकालय में नहीं)। यह सिर्फ एक पुस्तकालय के साथ संघर्ष होने की संभावना है। यह बहुत उपयोगी नहीं है क्योंकि लगभग हर चर को स्कूप किया जाता है, लेकिन यह उपयोगी हुआ करता था। यह भी (शायद) चर को आसानी से पहचानने में मदद करता है।
मैथ्यू

1
अफसोस की बात है कि क्रोम में DOMParserकाम नहीं है text/html, यह एमडीएन पृष्ठ वर्कअराउंड देता है।
जोकेस्टर

सुरक्षा नोट: यह बिना किसी ब्राउज़र संदर्भ के निष्पादित होगा, इसलिए कोई स्क्रिप्ट नहीं चलेगी। यह अविश्वसनीय इनपुट के लिए उपयुक्त होना चाहिए।
लीफ अर्ने कोर्सेट

6

Chrome और फ़ायरफ़ॉक्स में HTML को पार्स करने का सबसे तेज़ तरीका है # createContextualFragment:

var range = document.createRange();
range.selectNode(document.body); // required in Safari
var fragment = range.createContextualFragment('<h1>html...</h1>');
var firstNode = fragment.firstChild;

मैं एक सहायक समारोह बनाने की सलाह दूंगा, जो कि उपलब्ध हो तो क्रोनटैक्चुअल फ़्रेग्मेंट का उपयोग करता है और अन्यथा इनर HTML पर वापस गिरता है।

बेंचमार्क: http://jsperf.com/domparser-vs-createelement-innerhtml/3


ध्यान दें कि, की तरह (सरल) innerHTML, यह एक निष्पादित करेंगे <img>की onerror
Ry-

इसके साथ एक मुद्दा यह है कि, html '<td> test </ td>' जैसे दस्तावेज़ में td को अनदेखा करेगा। कोई संदर्भ (और केवल 'test' टेक्स्ट नोड बनाएँ) .OTOH, यदि यह आंतरिक रूप से एक टेम्प्लेट इंजन में उपयोग किया जाता है। तब सही संदर्भ उपलब्ध होगा।
मुनव्वर

इसके अलावा BTW, IE 11 createContextualFragment का समर्थन करता है।
मुनव्वर

सवाल यह था कि जेएस के साथ पार्स कैसे किया जाए - क्रोम या फ़ायरफ़ॉक्स नहीं
समुद्र 26.2

सुरक्षा नोट: यह इनपुट में किसी भी स्क्रिप्ट को निष्पादित करेगा, और इस प्रकार अविश्वसनीय इनपुट के लिए अनुपयुक्त है।
लीफ अर्ने स्टॉरसेट

6

निम्नलिखित फ़ंक्शन parseHTMLया तो वापस आ जाएगा:

  • एक Documentजब आपकी फ़ाइल एक डॉक प्रकार के साथ शुरू होता है।

  • एक DocumentFragmentअपनी फ़ाइल एक doctype साथ शुरू नहीं करता है।


कोड :

function parseHTML(markup) {
    if (markup.toLowerCase().trim().indexOf('<!doctype') === 0) {
        var doc = document.implementation.createHTMLDocument("");
        doc.documentElement.innerHTML = markup;
        return doc;
    } else if ('content' in document.createElement('template')) {
       // Template tag exists!
       var el = document.createElement('template');
       el.innerHTML = markup;
       return el.content;
    } else {
       // Template tag doesn't exist!
       var docfrag = document.createDocumentFragment();
       var el = document.createElement('body');
       el.innerHTML = markup;
       for (i = 0; 0 < el.childNodes.length;) {
           docfrag.appendChild(el.childNodes[i]);
       }
       return docfrag;
    }
}

कैसे इस्तेमाल करे :

var links = parseHTML('<!doctype html><html><head></head><body><a>Link 1</a><a>Link 2</a></body></html>').getElementsByTagName('a');

मैं IE8 पर काम करने के लिए इसे प्राप्त नहीं कर सका। मुझे फ़ंक्शन में पहली पंक्ति के लिए "ऑब्जेक्ट इस संपत्ति या विधि का समर्थन नहीं करता है" त्रुटि मिलती है। मुझे नहीं लगता कि createHTMLDocument फ़ंक्शन मौजूद है
सेबेस्टियन कैरोल

वास्तव में आपका उपयोग मामला क्या है? यदि आप केवल HTML को पार्स करना चाहते हैं और आपका HTML आपके दस्तावेज़ के मुख्य भाग के लिए है, तो आप निम्न कार्य कर सकते हैं: (1) var div = document.createElement ("DIV"); (२) div.innerHTML = मार्कअप; (3) परिणाम = div.childNodes; --- इससे आपको चाइल्डनॉड्स का संग्रह मिलता है और इसे न केवल IE8 में बल्कि IE6-7 में भी काम करना चाहिए।
जॉन सेलर्स

वैकल्पिक विकल्प के लिए धन्यवाद, मैं इसे फिर से करने की आवश्यकता होने पर कोशिश करूँगा। अभी के लिए हालांकि मैंने ऊपर JQuery समाधान का उपयोग किया है।
सेबेस्टियन कैरोल

@SebastianCarroll ध्यान दें कि IE8 trimस्ट्रिंग्स पर विधि का समर्थन नहीं करता है । देखें stackoverflow.com/q/2308134/3210837
टूथब्रश

2
@Toothbrush: क्या IE8 का समर्थन 2017 की भोर में अभी भी प्रासंगिक है?
जॉन सेलर्स ने

4

यदि आप jQuery का उपयोग करने के लिए खुले हैं, तो HTML के तारों से अलग डोम तत्व बनाने के लिए कुछ अच्छी सुविधाएं हैं। फिर इन्हें सामान्य साधनों के माध्यम से समझा जा सकता है, जैसे:

var html = "<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>";
var anchors = $('<div/>').append(html).find('a').get();

संपादित करें - अभी देखा @ फ्लोरियन का उत्तर जो सही है। यह मूल रूप से वही है जो उन्होंने कहा था, लेकिन jQuery के साथ।


4
const parse = Range.prototype.createContextualFragment.bind(document.createRange());

document.body.appendChild( parse('<p><strong>Today is:</strong></p>') ),
document.body.appendChild( parse(`<p style="background: #eee">${new Date()}</p>`) );


Nodeमाता-पिता Node(शुरुआत Range) के भीतर केवल वैध बच्चे को पार्स किया जाएगा। अन्यथा, अप्रत्याशित परिणाम हो सकते हैं:

// <body> is "parent" Node, start of Range
const parseRange = document.createRange();
const parse = Range.prototype.createContextualFragment.bind(parseRange);

// Returns Text "1 2" because td, tr, tbody are not valid children of <body>
parse('<td>1</td> <td>2</td>');
parse('<tr><td>1</td> <td>2</td></tr>');
parse('<tbody><tr><td>1</td> <td>2</td></tr></tbody>');

// Returns <table>, which is a valid child of <body>
parse('<table> <td>1</td> <td>2</td> </table>');
parse('<table> <tr> <td>1</td> <td>2</td> </tr> </table>');
parse('<table> <tbody> <td>1</td> <td>2</td> </tbody> </table>');

// <tr> is parent Node, start of Range
parseRange.setStart(document.createElement('tr'), 0);

// Returns [<td>, <td>] element array
parse('<td>1</td> <td>2</td>');
parse('<tr> <td>1</td> <td>2</td> </tr>');
parse('<tbody> <td>1</td> <td>2</td> </tbody>');
parse('<table> <td>1</td> <td>2</td> </table>');

सुरक्षा नोट: यह इनपुट में किसी भी स्क्रिप्ट को निष्पादित करेगा, और इस प्रकार अविश्वसनीय इनपुट के लिए अनुपयुक्त है।
लीफ अर्ने स्टॉरसेट

0

इस सरल कोड के साथ आप ऐसा कर सकते हैं:

let el = $('<div></div>');
$(document.body).append(el);
el.html(`<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>`);
console.log(el.find('a[href="test0"]'));
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.