2016-12-14 35 views
-3

まずはJavaScriptの専門家ではなく、実際には初心者です。Javascript Regexで文字列内のすべての出現を取得する

私はPHPを知っており、正規表現パターンのすべての出現を得るための関数がありますpreg_match()preg_match_all()です。

私は、文字列内のすべての発生を取得する方法を示す多くのリソースを見つけました。しかし、私はいくつかの正規表現マッチを行うと、それは私には醜いように見えます。

これは私がインターネットで見つけたものです:

var fileList = [] 
var matches 
while ((matches = /<item id="(.*?)" href="(.*?)" media-type="(?:.*?)"\/>/g.exec(data)) !== null) { 
    fileList.push({id: matches[1], file: matches[2]}) 
} 

fileOrder = [] 
while ((matches = /<itemref idref="(.*?)"\/>/g.exec(data)) !== null) { 
    fileOrder.push({id: matches[1]}) 
} 

このコード以外のよりエレガントな方法はありますか?

+0

そして、あなたの質問はありますか? –

+0

Ohh。私はこれが間違っていたと思う私は、このような何かが必要な場合、私のような初心者に知識を共有しようとしました。そうするために私の質問に答えてもらえますか? – Valour

+0

これはQ&Aサイトであり、フォーラムではありません。プログラミングに関する特定の質問がない限り、これを削除する必要があります。あなたはこれを "私がここで使ったアプローチの問題は何ですか?"それはhttp://codereview.stackexchange.com/に適しています。 –

答えて

1

regexesには、平凡な括弧やHTML/XMLのオープン/クローズタグなど、任意のネストされたオカレンスを確実に一致させるのに十分なパワーが不足しているため、一般的には悪い考えです。文字列のように扱わなくても、JavaScriptでDOMからデータを取得するのは簡単ですが、それはのDOMです。たとえば:

let mapOfIDsToFiles = Array.from(document.querySelectorAll('item')) 
    .reduce((obj, item) => { 
    obj[item.id] = item.href; 
    return obj; 
    }, {}); 

これは単純で、そしてより堅牢、ずっと速いという利点があります。 DOMのアクセスは遅いですが、とにかく正規表現を実行するHTMLを取得するには、DOMにアクセスします。

String.prototypeのような組み込みプロトタイプを変更すると、同じ機能を定義するサードパーティのコードでランダムに破損する可能性があるため、またはJavaScript標準がその関数を含むように更新されるそれは異なった働きをします。

UPDATE

データはすでに文字列である場合は、簡単にページに影響を与えることなく、DOM要素にそれを回すことができます。

let elem = document.createElement('div') 
div.innerHTML = data; 
div.querySelectorAll('item'); // gives you all the item elements 

限り、あなたは文書に付加していないとして、 、メモリ内のJavaScriptオブジェクトです。

UPDATE 2

はい、これはまた、XMLのために動作しますが、DOMに変換することはもう少し複雑です:構文解析に失敗した場合ということ

// define the function differently if IE, both do the same thing 
let parseXML = (typeof window.DOMParser != null && typeof window.XMLDocument != null) ? 
    xml => (new window.DOMParser()).parseFromString(xml, 'text/xml') : 
    xml => { 
    let xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM'); 
    xmlDoc.async = "false"; 
    xmlDoc.loadXML(xml); 
    return xmlDoc; 
    }; 

let xmlDoc = parseXML(data).documentElement; 

let items = Array.from(xmlDoc.querySelectorAll('item')); 

注(すなわち、あなたの文書は、不正な形式でした)、その後、あなたはそうのようなエラー文書をチェックする必要があります。

// check for error document 
(() => { 
    let firstTag = xmlDoc.firstChild.firstChild; 
    if (firstTag && firstTag.tagName === 'parsererror') { 
    let message = firstTag.children[1].textContent; 
    throw new Error(message); 
    } 
})(); 
+0

しかし、 'data'変数はDOMにロードされません。それはファイルからのものです。文字列をページの実際のDOMに触れずに別個のDOMに変換する方法が分かっているなら、それはすばらしいでしょう。 – Valour

+0

@GokhanOzturkが私の答えを更新しました。 –

+0

文字列が実際にXML文書の場合はこれも機能しますか? – Valour

0

私はStringでメソッドを作成するという考えを思いつきました。

私は私のために物事をsimplyfy String.prototypeを書いた:

String.prototype.getMatches = function(regex, callback) { 
    var matches = [] 
    var match 
    while ((match = regex.exec(this)) !== null) { 
    if (callback) 
     matches.push(callback(match)) 
    else 
     matches.push(match) 
    } 

    return matches 
} 

今、私はもっとエレガントな方法ですべての一致を得ることができます。また、それはPHPのpreg_match_all()の機能に似ています。

var fileList = data.getMatches(/<item id="(.*?)" href="(.*?)" media-type="(?:.*?)"\/>/g, function(matches) { 
    return {id: matches[1], file: matches[2]} 
}) 

var fileOrder = data.getMatches(/<itemref idref="(.*?)"\/>/g, function(matches) { 
    return matches[1] 
}) 

この情報もお役に立てば幸いです。

関連する問題