জেএস দিয়ে একটি HTML স্ট্রিং পার্স করুন


258

আমি একটি সমাধান অনুসন্ধান করেছিলাম তবে কিছুই প্রাসঙ্গিক ছিল না, তাই এখানে আমার সমস্যা:

আমি একটি স্ট্রিং পার্স করতে চাই যাতে এইচটিএমএল পাঠ্য রয়েছে। আমি এটি জাভাস্ক্রিপ্টে করতে চাই।

আমি এই লাইব্রেরিটি চেষ্টা করেছি তবে মনে হচ্ছে এটি আমার বর্তমান পৃষ্ঠার এইচটিএমএলকে কোনও স্ট্রিং থেকে নয়, পার্স করেছে। কারণ আমি যখন নীচের কোডটি চেষ্টা করি তখন এটি আমার পৃষ্ঠার শিরোনাম পরিবর্তন করে:

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

আমার লক্ষ্য হ'ল একটি স্ট্রিংয়ের মতো পড়া এইচটিএমএল বাহ্যিক পৃষ্ঠা থেকে লিঙ্কগুলি বের করা।

আপনি এটি করতে কোনও এপিআই জানেন?



1
লিঙ্কযুক্ত নকলের পদ্ধতিটি প্রদত্ত স্ট্রিং থেকে একটি HTML ডকুমেন্ট তৈরি করে। তারপরে, আপনি doc.getElementsByTagName('a')লিঙ্কগুলি (বা এমনকি doc.links) পড়তে ব্যবহার করতে পারেন ।
রব ডাব্লু

এটা তোলে এর মূল্য উল্লেখ যে আপনার React.js মত একটি কাঠামো ব্যবহার করছেন তারপর এরকম উপায়গুলির যেমন ফ্রেমওয়ার্ক নির্দিষ্ট হতে পারে: stackoverflow.com/questions/23616226/...
মাইক লেয়ন

উত্তর:


373

একটি ডামি ডিওএম উপাদান তৈরি করুন এবং এতে স্ট্রিং যুক্ত করুন। তারপরে, আপনি এটি কোনও ডিওএম উপাদানগুলির মতো চালনা করতে পারেন।

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> এবং <শিরোনাম> ট্যাগটি হারাব ....
মঞ্চে

2
সমস্যা: আমার <ফ্রেম> ট্যাগ থেকে লিঙ্কগুলি নেওয়া দরকার। তবে এই সমাধানের সাহায্যে ফ্রেম ট্যাগ মুছে ফেলা হয় ...
মঞ্চ

3
@ স্টেজ আমি পার্টিতে কিছুটা দেরি করেছি, তবে আপনি এবং ট্যাগ document.createElement('html');সংরক্ষণে ব্যবহার করতে সক্ষম হবেন । <head><body>
omninonsense

3
দেখে মনে হচ্ছে আপনি এইচটিএমএল উপাদানটির মধ্যে এইচটিএমএল উপাদান
রাখছেন

6
আমি উদ্বিগ্ন শীর্ষ উত্তর হিসাবে upvated হয়। parse()নিচে সমাধান আরো reusable এবং মার্জিত।
জাস্টিন

232

এটি বেশ সহজ:

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

MDN এর মতে ক্রোমে এটি করার জন্য আপনাকে এক্সএমএল হিসাবে পার্স করতে হবে:

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
এেন্ড্রু

5
ওয়ার্থ লক্ষ করেন, নির্মিত দস্তাবেজে থাকা সমস্ত আপেক্ষিক লিংক ভাঙা হয়, কারণ নথি inheriting দ্বারা নির্মিত পরার documentURLএর windowস্ট্রিং এর URL থেকে, যা সম্ভবত আলাদা।
সিভিং

2
আপনার কেবলnew DOMParser একবার কল করা উচিত এবং তারপরে আপনার স্ক্রিপ্টের বাকি অংশে একই জিনিসটি পুনঃব্যবহার করা উচিত ing
জ্যাক গিফিন

1
parse()নিচে সমাধান আরো পুনর্ব্যবহারযোগ্য এবং HTML নির্দিষ্ট। আপনার যদি এক্সএমএল ডকুমেন্টের প্রয়োজন হয় তবে এটি দুর্দান্ত।
জাস্টিন

এই পার্স করা ওয়েবপৃষ্ঠাটি আমি কীভাবে কোনও ডায়লগ বাক্স বা অন্য কোনও উপায়ে প্রদর্শন করতে পারি? আমি এর সমাধান করতে সক্ষম হইনি
শরীক মুশারফ

18

সম্পাদনা: এইচটিএমএল, মাথা এবং শরীর অপসারণ হওয়ায় নীচের সমাধানটি কেবলমাত্র HTML "টুকরো" জন্য। আমি অনুমান করি যে এই প্রশ্নের সমাধানটি হ'ল ডোমপার্সারের পার্সফ্র্যামস্ট্রিং () পদ্ধতি।


এইচটিএমএল খণ্ডগুলির জন্য, এখানে তালিকাবদ্ধ সমাধানগুলি বেশিরভাগ এইচটিএমএল-র জন্য কাজ করে, তবে নির্দিষ্ট কিছু ক্ষেত্রে এটি কাজ করবে না।

উদাহরণস্বরূপ পার্সিংয়ের চেষ্টা করুন <td>Test</td>। এটি ডিভিনিয়ারএইচটিএমএল সমাধানে বা ডিওএমপার্সার.প্রোটোটাইপ.পার্সফ্রস্ট্রিং বা রেঞ্জ.ক্রিয়েট কনটেক্সটুয়াল ফ্রেমমেন্ট দ্রব্যে কাজ করবে না। টিডি ট্যাগটি নিখোঁজ হয়ে যায় এবং কেবলমাত্র পাঠ্য অবশিষ্ট থাকে।

কেবল jQuery সেই কেসটি ভালভাবে পরিচালনা করে।

সুতরাং ভবিষ্যতের সমাধান (এমএস এজ 13+) হ'ল টেমপ্লেট ট্যাগটি ব্যবহার করা:

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

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

পুরানো ব্রাউজারগুলির জন্য আমি jQuery এর পার্সএইচটিএমএল () পদ্ধতিটি একটি স্বাধীন গিস্টে বের করেছি - https://gist.github.com/Munawwar/6e6362dbdf77c7865a99


আপনি যদি পুরানো ব্রাউজারগুলিতেও কাজ করে ফরোয়ার্ড-সামঞ্জস্যপূর্ণ কোড লিখতে চান তবে আপনি ট্যাগটি পলফিল<template> করতে পারেন । এটি কাস্টম উপাদানগুলির উপর নির্ভর করে যা আপনাকে পলিফিলের প্রয়োজনও হতে পারে । বাস্তবে আপনি পলফিল কাস্টম উপাদান, টেমপ্লেট, ছায়া ডোম, প্রতিশ্রুতি এবং একসাথে কিছু অন্যান্য জিনিস পল করার জন্য কেবল ওয়েবকম্পোনেন্টস.জেএস ব্যবহার করতে চাইতে পারেন।
জেফ লাফলিন

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

4
আপনি উপসর্গ করছেন কেন $? এছাড়াও, লিঙ্কযুক্ত সদৃশ হিসাবে উল্লিখিত , text/htmlখুব ভাল সমর্থন করা হয় না, এবং একটি পলিফিল ব্যবহার করে বাস্তবায়ন করতে হবে।
রব ডব্লিউ

1
আমি একটি প্রকল্প থেকে এই লাইনটি অনুলিপি করেছি, আমি জাভাস্ক্রিপ্ট অ্যাপ্লিকেশনটিতে (লাইব্রেরিতে নয়) ভেরিয়েবলের উপসর্গ ব্যবহার করতে চাইছি to এটি কেবল একটি লাইব্রেরির সাথে দ্বন্দ্ব এড়ানো এড়ানো। এটি খুব দরকারী না কারণ প্রায় প্রতিটি ভেরিয়েবল স্কোপড হয় তবে এটি ব্যবহারযোগ্য ছিল। এটি (সম্ভবত) সহজেই ভেরিয়েবলগুলি সনাক্ত করতে সহায়তা করে।
ম্যাথিউ

1
দু: খজনকভাবে ক্রোমে DOMParserকাজ করা হয় text/htmlনা, এই এমডিএন পৃষ্ঠাটি কার্যবিবরণী দেয়।
জোকসটার

সুরক্ষা নোট: এটি কোনও ব্রাউজারের প্রসঙ্গ ছাড়াই কার্যকর হবে, সুতরাং কোনও স্ক্রিপ্ট চলবে না। এটি অবিশ্বস্ত ইনপুট জন্য উপযুক্ত হতে হবে।
লিফ আরে স্টারসেট

6

ক্রোম এবং ফায়ারফক্সে এইচটিএমএল পার্স করার দ্রুততম উপায় হ'ল রেঞ্জ # ক্রিয়েট কনটেক্সটুয়াল ফ্রেমমেন্ট:

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

আমি একটি সহায়ক ফাংশন তৈরির প্রস্তাব দিচ্ছি যা উপলব্ধ থাকলে ক্রেন্টেক্সটচুয়ালফ্র্যাগমেন্ট ব্যবহার করে এবং অন্যথায় অভ্যন্তরীণ এইচটিএমএল এ ফিরে আসে।

বেঞ্চমার্ক: http://jsperf.com/domparser-vs-createelement-innerhtml/3


উল্লেখ্য, মত (সাধারণ) innerHTML, এই একটি চালানো হবে <img>এর onerror
রাই-

এটির সাথে একটি সমস্যা হ'ল, '<td> পরীক্ষা </td>' এর মতো এইচটিএমএল ডকুমেন্ট.এই প্রসঙ্গে টিডিকে উপেক্ষা করবে (এবং কেবল 'টেস্ট' টেক্সট নোড তৈরি করবে) .OTOH, যদি এটি কোনও টেম্প্লেটিং ইঞ্জিনে অভ্যন্তরীণভাবে ব্যবহৃত হয় তাহলে সঠিক প্রসঙ্গ উপলব্ধ হবে।
মুনাওয়ার

এছাড়াও বিটিডাব্লু, আইই 11 ক্রিয়েট কনটেক্সটুয়াল ফ্রেমমেন্টকে সমর্থন করে।
মুনাওয়ার

প্রশ্নটি কীভাবে
জেএসের

সুরক্ষা নোট: এটি ইনপুটটিতে যে কোনও স্ক্রিপ্ট কার্যকর করবে এবং এইভাবে অবিশ্বস্ত ইনপুট জন্য অনুপযুক্ত।
লিফ আরে স্টারসেট

6

নিম্নলিখিত ফাংশন parseHTMLহয় ফিরে আসবে:

  • একটি Documentযখন আপনার ফাইল ডক্টাইপ দিয়ে শুরু হয়।

  • একটি DocumentFragmentযখন আপনার ফাইল ডক্টাইপ দিয়ে শুরু হয় না।


কোড :

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

আমি এটি আইই 8 তে কাজ করতে পারি না। ফাংশনের প্রথম লাইনের জন্য আমি "ত্রুটিটি এই সম্পত্তি বা পদ্ধতিটিকে সমর্থন করে না" ত্রুটি পেয়েছি। আমি মনে করি না যে এইচটিএমএল ডকুমেন্ট ফাংশনটি বিদ্যমান
সেবাস্তিয়ান ক্যারল

আপনার ব্যবহারের ক্ষেত্রে ঠিক কী? আপনি যদি কেবল এইচটিএমএলকে বিশ্লেষণ করতে চান এবং আপনার এইচটিএমএলটি আপনার নথির বডির উদ্দেশ্যে করা হয়, আপনি নিম্নলিখিতগুলি করতে পারেন: (1) var Div = document.createElement ("DIV"); (2) div.innerHTML = মার্কআপ; (3) ফলাফল = div.childNodes; --- এটি আপনাকে চাইল্ডনোডগুলির একটি সংকলন দেয় এবং কেবল আইই 8 তে নয়, এমনকি আই 6-7 এও কাজ করা উচিত।
জন স্লেজার

বিকল্প বিকল্পের জন্য ধন্যবাদ, আমি যদি আবার এটি করার দরকার হয় তবে আমি এটি চেষ্টা করব। আপাতত যদিও আমি উপরে JQuery সমাধানটি ব্যবহার করেছি।
সেবাস্তিয়ান ক্যারল

@ সেবাস্তিয়ানকারোল নোট করুন আইই trim8 স্ট্রিংয়ের পদ্ধতিটিকে সমর্থন করে না । Stackoverflow.com/q/2308134/3210837 দেখুন ।
টুথব্রাশ 21

2
@ টুথব্রাশ: আইই 8 সমর্থনটি এখনও 2017 ভোরের দিকে প্রাসঙ্গিক?
জন স্লেজার 14

4

আপনি যদি jQuery ব্যবহারের জন্য উন্মুক্ত হন তবে এটিতে HTML এর স্ট্রিং থেকে বিচ্ছিন্ন DOM উপাদান তৈরি করার জন্য কিছু সুন্দর সুবিধা রয়েছে। এরপরে এগুলি স্বাভাবিক উপায়ে অনুসন্ধান করা যেতে পারে, যেমন:

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"]'));
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.