2

これは前の質問の続きです: Parse.com の Cloud Code で JavaScript で XML を Json に変換する必要があります

正規表現がこれに適しているとは思わないため、反対票を投じないでください。それは私が働かなければならないものです。 これを行う方法の別のアイデアがある場合は、お知らせください。ただし、Parse.com の Cloud Code で実行する必要があります。

元の XML:

<?xml version="1.0" encoding="UTF-8" ?><api><products total-matched="1618" records-returned="1" page-number="1"><product><ad-id>1234</ad-id><supplier-name>Window World</supplier-name><supplier-category>3703703</supplier-category><buy-url>http://website.com</buy-url><currency>USD</currency><description>Window</description><image-url>http://website.com/windowa/80x80.jpg</image-url><in-stock>yes</in-stock><manufacturer-name>Window World</manufacturer-name><name>Half Pain Glass</name><price>31.95</price><retail-price>87.60</retail-price><sale-price>29.95</sale-price><sku>5938</sku><upc></upc></product><product><ad-id>1234</ad-id><supplier-name>Window World</supplier-name><supplier-category>3703703</supplier-category><buy-url>http://website.com</buy-url><currency>USD</currency><description>Window</description><image-url>http://website.com/windowa/80x80.jpg</image-url><in-stock>yes</in-stock><manufacturer-name>Window World</manufacturer-name><name>Half Pain Glass</name><price>31.95</price><retail-price>87.60</retail-price><sale-price>29.95</sale-price><sku>5938</sku><upc></upc></product><product><ad-id>1234</ad-id><supplier-name>Window World</supplier-name><supplier-category>3703703</supplier-category><buy-url>http://website.com</buy-url><currency>USD</currency><description>Window</description><image-url>http://website.com/windowa/80x80.jpg</image-url><in-stock>yes</in-stock><manufacturer-name>Window World</manufacturer-name><name>Half Pain Glass</name><price>31.95</price><retail-price>87.60</retail-price><sale-price>29.95</sale-price><sku>5938</sku><upc></upc></product><product><ad-id>1234</ad-id><supplier-name>Window World</supplier-name><supplier-category>3703703</supplier-category><buy-url>http://website.com</buy-url><currency>USD</currency><description>Window</description><image-url>http://website.com/windowa/80x80.jpg</image-url><in-stock>yes</in-stock><manufacturer-name>Window World</manufacturer-name><name>Half Pain Glass</name><price>31.95</price><retail-price>87.60</retail-price><sale-price>29.95</sale-price><sku>5938</sku><upc></upc></product></products></api>

正規表現コード:

var regex = /(<\w+[^<]*?)\s+([\w-]+)="([^"]+)">/;
            while(xml.match(regex)) xml = xml.replace(regex, '<$2>$3</$2>$1>'); // For attributes

            xml = xml.replace(/\s/g, ' ').  // Finds all the white space converts to single space
                    replace(/< *\?[^>]*?\? *>/g, ''). //Finds the XML header and removes it
                    replace(/< *!--[^>]*?-- *>/g, ''). //Finds and removes all comments
                    replace(/< *(\/?) *(\w[\w-]+\b):(\w[\w-]+\b)/g, '<$1$2_$3').
                    replace(/< *(\w[\w-]+\b)([^>]*?)\/ *>/g, '< $1$2>').
                    replace(/(\w[\w-]+\b):(\w[\w-]+\b) *= *"([^>]*?)"/g, '$1_$2="$3"').
                    replace(/< *(\w[\w-]+\b)((?: *\w[\w-]+ *= *" *[^"]*?")+ *)>( *[^< ]*?\b.*?)< *\/ *\1 *>/g, '< $1$2 value="$3">').
                    //replace(/ *(\w[\w-]+\b) *= *"([^>]*?)" */g, '< $1>$2').
                    replace(/< *(\w[\w-]+\b) *</g, '<$1>< ').
                    replace(/> *>/g, '>').
                    //replace(/< *\/ *(\w[\w-]+\b) *> *< *\1 *>/g, '').  // breaks the output?
                    replace(/"/g, '\\"').
                    replace(/< *(\w[\w-]+\b) *>([^<>]*?)< *\/ *\1 *>/g, '"$1":"$2",').
                    replace(/< *(\w[\w-]+\b) *>([^<>]*?)< *\/ *\1 *>/g, '"$1":{$2},').
                    replace(/< *(\w[\w-]+\b) *>(?=.*?< \/\1\},\{)/g, '"$1":[{').
                    split(/\},\{/).
                    reverse().
                    join('},{').
                    replace(/< *\/ *(\w[\w-]+\b) *>(?=.*?"\1":\[\{)/g, '}],').
                    split(/\},\{/).
                    reverse().
                    join('},{').
                    replace(/< \/(\w[\w-]+\b)\},\{\1>/g, '},{').
                    replace(/< *(\w[\w-]+\b)[^>]*?>/g, '"$1":{').
                    replace(/< *\/ *\w[\w-]+ *>/g,'},').
                    replace(/\} *,(?= *(\}|\]))/g, '}').
                    replace(/] *,(?= *(\}|\]))/g, ']').
                    replace(/" *,(?= *(\}|\]))/g, '"').
                    replace(/ *, *$/g, '');

出力:

"api": {
    "page-number": "1",
    "records-returned": "1",
    "total-matched": "1618",
    "products": {
        "product": {
            "ad-id": "1234",
            "supplier-name": "Window World",
            "supplier-category": "3703703",
            "buy-url": "http://website.com",
            "currency": "USD",
            "description": "Window",
            "image-url": "http://website.com/windowa/80x80.jpg",
            "in-stock": "yes",
            "manufacturer-name": "Window World",
            "name": "Half Pain Glass",
            "price": "31.95",
            "retail-price": "87.60",
            "sale-price": "29.95",
            "sku": "5938",
            "upc": ""
        },
        "product": {
            "ad-id": "1234",
            "supplier-name": "Window World",
            "supplier-category": "3703703",
            "buy-url": "http://website.com",
            "currency": "USD",
            "description": "Window",
            "image-url": "http://website.com/windowa/80x80.jpg",
            "in-stock": "yes",
            "manufacturer-name": "Window World",
            "name": "Half Pain Glass",
            "price": "31.95",
            "retail-price": "87.60",
            "sale-price": "29.95",
            "sku": "5938",
            "upc": ""
        },
        "product": {
            "ad-id": "1234",
            "supplier-name": "Window World",
            "supplier-category": "3703703",
            "buy-url": "http://website.com",
            "currency": "USD",
            "description": "Window",
            "image-url": "http://website.com/windowa/80x80.jpg",
            "in-stock": "yes",
            "manufacturer-name": "Window World",
            "name": "Half Pain Glass",
            "price": "31.95",
            "retail-price": "87.60",
            "sale-price": "29.95",
            "sku": "5938",
            "upc": ""
        },
        "product": {
            "ad-id": "1234",
            "supplier-name": "Window World",
            "supplier-category": "3703703",
            "buy-url": "http://website.com",
            "currency": "USD",
            "description": "Window",
            "image-url": "http://website.com/windowa/80x80.jpg",
            "in-stock": "yes",
            "manufacturer-name": "Window World",
            "name": "Half Pain Glass",
            "price": "31.95",
            "retail-price": "87.60",
            "sale-price": "29.95",
            "sku": "5938",
            "upc": ""
        }
    }
}

これに関して私が抱えている最後の問題 (私が知っていること) は、繰り返し項目が JSON 配列にならないことです。これを解決する方法についてのアイデアはありますか?

4

2 に答える 2

2

正規表現の使用は興味深いアプローチであり、ノード リストを操作するよりも少し高速に思えます。ただし、(OP のアプリケーションのように) 速度が決定要因でない場合、これは xml を js に変換する最良の方法ではありません。正規表現コードは約 1kb 圧縮されています。同じバイト数の場合、かなり堅牢で再利用可能なコンバーターを構築できます...さまざまなブラウザーのxml名前空間にも対処できるコンバーターです。

次のコード (圧縮) を書き、OP の XML データを適切に処理しました。

    var xml2js=function(m,p){var f=1,o=2,d=3,n=4,j=7,c=8,h=9,l,b,a,k={},g=[];if(!p){p={}}if(typeof p=="string"){p={find:p}}p.xmlns=p.xmlns||"*";if(p.parse!="function"){p.parse=e}function e(i){return i.split(":").pop().replace(/^ows_/,"").replace(/[^a-z,A-Z,0-9]/g,"")}switch(m.nodeType){case h:a=(!p.find)?m.childNodes:(m.getElementsByTagNameNS)?m.getElementsByTagNameNS(p.xmlns,p.find.split(":").pop()):m.getElementsByTagName(p.find);for(l=0;l<a.length;l++){k=xml2js(a[l]);if(k){g.push(k)}}k=(g.length&&g.length==1)?g[0]:g;break;case f:if(m.attributes.length==0&&m.childNodes.length==1&&m.childNodes.item(0).nodeValue){k=m.childNodes.item(0).nodeValue}for(l=0;l<m.attributes.length;l++){b=p.parse(m.attributes.item(l).nodeName);k[b]=m.attributes.item(l).nodeValue}for(l=0;l<m.childNodes.length;l++){if(m.childNodes.item(l).nodeType!=d){b=p.parse(m.childNodes.item(l).nodeName);if(typeof k[b]=="undefined"){k[b]=xml2js(m.childNodes.item(l))}else{if(typeof k[b].push=="undefined"){k[b]=[k[b]]}k[b].push(xml2js(m.childNodes.item(l)))}}}break;case n:k="<![CDATA["+m.nodeValue+"]]>";break;case d:k=m.nodeValue;break;case c:k="";break;default:k=null}return k};

次に、xml をロードして変換します。

    function test( ) {
        var nodeName = 'products'; // optional - any node name
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'CloudCode.xml', false);
        xhr.send();
        var js = xml2js( xhr.responseXML, nodeName );
        console.log(JSON.stringify( js, null, '\t'));
    }

出力:

    {
    "pagenumber": "1",
    "recordsreturned": "1",
    "totalmatched": "1618",
     "product": [
      {
        "adid": "1234",
        "suppliername": "Window World",
        "suppliercategory": "3703703",
         "buyurl": "http://website.com",


         etc...
于 2014-03-30T02:23:39.887 に答える
1

わかりましたので、それは簡単な修正ですが、それでもうまくいくようです。これは配列構造を ADD するだけなので、同じキーを何度も持つことはありません (ただし、そのキーは破棄されません)。
変化する:

replace(/< *(\w[\w-]+\b) *>(?=.*?< \/\1\},\{)/g, '"$1":[{').
split(/\},\{/).
reverse().
join('},{').
replace(/< *\/ *(\w[\w-]+\b) *>(?=.*?"\1":\[\{)/g, '}],').
split(/\},\{/).
reverse().
join('},{').

これは、配列を実装しようとする試みです。
そして、置きます :

replace(/< *(\w[\w-]+\b) *>(?=("\w[\w-]+\b)":\{.*?\},\2)(.*?)< *\/ *\1 *>/, '"$1":[$3],')

私は物事を一致させる彼の方法をほとんど使用したことに注意してください. それは少なくともあなたの例ではうまくいったようです。

于 2013-03-28T10:57:16.933 に答える