名前空間を使用したXML解析にjQueryを使用する方法


82

私はjQueryを初めて使用し、XMLドキュメントを解析したいと思います。

デフォルトの名前空間を使用して通常のXMLを解析できますが、次のようなXMLを使用します。

<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
   <s:Schema id="RowsetSchema">
     <s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">
       <s:AttributeType name="ows_ID" rs:name="ID" rs:number="1">
        <s:datatype dt:type="i4" dt:maxLength="4" />
      </s:AttributeType>
       <s:AttributeType name="ows_DocIcon" rs:name="Type" rs:number="2">
        <s:datatype dt:type="string" dt:maxLength="512" />
      </s:AttributeType>
       <s:AttributeType name="ows_LinkTitle" rs:name="Title" rs:number="3">
        <s:datatype dt:type="string" dt:maxLength="512" />
      </s:AttributeType>
       <s:AttributeType name="ows_ServiceCategory" rs:name="Service Category" rs:number="4">
        <s:datatype dt:type="string" dt:maxLength="512" />
      </s:AttributeType>
    </s:ElementType>
  </s:Schema>
   <rs:data>
    <z:row ows_ID="2" ows_LinkTitle="Sample Data 1" />
    <z:row ows_ID="3" ows_LinkTitle="Sample Data 2" />
    <z:row ows_ID="4" ows_LinkTitle="Sample Data 3" />
  </rs:data>
</xml>

私が本当に欲しいのは<z:row>

これまで、私は以下を使用してきました:

$.get(xmlPath, {}, function(xml) {
    $("rs:data", xml).find("z:row").each(function(i) {
        alert("found zrow");
    });
}, "xml");

本当に運がない。何か案は?


名前空間プレフィックスを省略するとうまくいきました。この回答を参照してください:stackoverflow.com/a/25089647/2539811
Vincil Bishop 2017年

回答:


135

わかった。

\\コロンを脱出する必要があることが判明しました。

$.get(xmlPath, {}, function(xml) {
    $("rs\\:data", xml).find("z\\:row").each(function(i) {
        alert("found zrow");
    });
}, "xml");

リッチが指摘したように:

より良い解決策は、エスケープする必要がなく、すべての「最新の」ブラウザで機能します。

.find("[nodeName=z:row]")

2
$('[nodeName=rs:data]', xml).find('[nodeName=z:row]')
--WebKitの

2
これはjQueryバージョン1.4.4では機能しなくなったようです。つまり、jQueryのXML名前空間のサポートが優れていると思います。安全のために、これは機能します$('[nodeName=rs:data],data')
Josh Pearce

15
現在、jQuery 1.7がリリースされており、この最後のソリューションは機能しなくなりました。新しい方法は何ですか?
Gapipro 2011

3
jQuery 1.8.xでは、機能しなくなりました。ここで説明するように、カスタムの疑似クラス互換性の回避策を使用して実行する必要があります
miere 2012

5
これは特定のXMLドキュメントの質問に答えますが、接頭辞がのようなrsdtまたはs実際には名前空間ではないことを人々に思い出させたいと思います。名前空間は、ファイルの先頭にあるURNです。プレフィックスは、ドキュメントの作成者が短くするために選択したエイリアスです。同じ名前空間に一致する同じドキュメントを、まったく異なるプレフィックスで作成できます。クエリでプレフィックスを想定するのではなく、名前空間を理解するAPIを探すことをお勧めします。あなたが使用することができ、ブラウザのDOM APIの例、getElementByTagNameNS()およびgetAttributeNS()
セルジオペレイラ2014

35

私はプラグインとあらゆる種類のソリューションについてのこの読書に数時間を費やしましたが、運がありませんでした。

ArnisAndyはjQueryディスカッションへのリンクを投稿しました。この回答が提供されており、Chrome(v18.0)、FireFox(v11.0)、IE(v9.08)、Safari(v5.1.5)でこれが機能することを確認できます。 )jQuery(v1.7.2)を使用します。

コンテンツの名前が<content:encoded>であるWordPressフィードをスクレイプしようとしていますが、これがうまくいきました。

content: $this.find("content\\:encoded, encoded").text()

3
これは、最新のjQuery(同じバージョン)を使用して確実に機能した唯一のものでした。ありがとうございます。
ドミニクK

2
これは、.each()ループを使用してitem要素を反復処理しているときに機能しました$('dc\\:creator, creator', this).text()。ただし、なぜ追加, creatorが必要なのかはわかりませんが、機能するdc\\:creatorだけではありませんでした。
フィリップペイトン2014

20

jquery 1.5を使用している場合は、ノードセレクターの属性値を引用符で囲んで機能させる必要があります。

.find('[nodeName="z:row"]')

19

上記の答えは正しいようですが、Webkitブラウザ(Safari、Chrome)では機能しません。私が信じるより良い解決策は次のとおりです:

.find("[nodeName=z:myRow, myRow]")    

5
これはjQueryバージョン1.4.4では機能しなくなったようです。つまり、jQueryのXML名前空間のサポートが優れていると思います。安全のために、これは機能します$('[nodeName=rs:data],data')
Josh Pearce

16

誰かがjQueryなしで、通常のJavascriptだけで、そしてGoogle Chrome(webkit)でこれを行う必要がある場合、これは私が多くの調査とテストの後にそれを機能させるために見つけた唯一の方法です。

parentNode.getElementsByTagNameNS("*", "name");

これは、次のノードを取得するために機能します<prefix:name>。ご覧のとおり、プレフィックスまたは名前空間は省略されており、タグ名がname。の場合、異なる名前空間の要素と一致します。しかし、うまくいけば、これはあなたにとって問題にならないでしょう。

これはどれも私にはうまくいきませんでした(私はGoogle Chrome拡張機能を開発しています):

getElementsByTagNameNS("prefix", "name")

getElementsByTagName("prefix:name")

getElementsByTagName("prefix\\:name")

getElementsByTagName("name")

編集:スリープ後、回避策が見つかりました:)この関数は、次のnodeNameように完全に一致する最初のノードを返します<prefix:name>

// Helper function for nodes names that include a prefix and a colon, such as "<yt:rating>"
function getElementByNodeName(parentNode, nodeName)
{   
    var colonIndex = nodeName.indexOf(":");
    var tag = nodeName.substr(colonIndex + 1);
    var nodes = parentNode.getElementsByTagNameNS("*", tag);
    for (var i = 0; i < nodes.length; i++)
    {
        if (nodes[i].nodeName == nodeName) return nodes[i]
    }
    return undefined;
}

一致するすべての要素を返す必要がある場合は、簡単に変更できます。それが役に立てば幸い!


14

上記の解決策はどれもうまく機能しません。私はこれを見つけて、速度が改善されました。これを追加するだけで、魅力のように機能します:

$.fn.filterNode = function(name) {
    return this.find('*').filter(function() {
       return this.nodeName === name;
    });
};

使用法:

var ineedthatelementwiththepsuedo = $('someparentelement').filterNode('dc:creator');

ソース:http//www.steveworkman.com/html5-2/javascript/2011/improving-javascript-xml-node-finding-performance-by-2000/


スニペットをありがとう-これは非常に役立ちます/問題を解決します。
ギルマン


3

jQuery 1.7の時点で、名前空間付き要素を見つけるためのいくつかの回避策に問題があったことは注目に値します。詳細については、次のリンクを参照してください。


パフォーマンスが重要な場合、最善の解決策はjQueryなしでタグを選択することです。比較については、以下を参照してください。jsperf.com

3

コメントで解決策が見つかりました:jQuery $()。findを使用した名前空間でのXMLの解析

コロンが機能した後、ノード名の後半を使用します。使用済み.find( "LAT")の代わりに、.find( "GEO \:LAT")と、それは私のために働きました。


私のセットアップ:

  • Chrome 42
  • jQuery 2.1.3

サンプルXML(GoogleコンタクトAPIからのスニペット):

<entry>
  <id>http://www.google.com/m8/feeds/contacts/mstefanow%40gmail.com/base/0</id>
  <gd:email rel="http://schemas.google.com/g/2005#other" address="email@example.com" primary="true"/>
</entry>

コードの解析:

var xmlDoc = $.parseXML( xml );
var $xml = $( xmlDoc );
var $emailNode = $xml.find( "email" );
$("#email").html($emailNode.attr("address"));

Plnkr:http://plnkr.co/edit/l8VzyDq1NHtn5qC9zTjf?p = preview


私が助けてくれてうれしいです:)
マイクグレース

2

jQuery 1.7は、以下では機能しません。

$(xml).find("[nodeName=a:IndexField2]")

私がChrome、Firefox、およびIEで機能するようになった1つの解決策は、一方がIEで機能し、もう一方がChromeで機能するという事実に基づいて、IEで機能するセレクターとChromeで機能するセレクターを使用することです。

$(xml).find('a\\\\:IndexField2, IndexField2')

IEでは、これは名前空間を使用してノードを返します(FirefoxとIEには名前空間が必要です)。Chromeでは、セレクターは非名前空間セレクターに基づいてノードを返します。私はこれをSafariでテストしていませんが、Chromeで動作しているので動作するはずです。


2

私の解決策(Phpプロキシを使用しているため)は、:namespaceを_ ...に置き換えることです。したがって、名前空間の問題はもうありません;-)

複雑にしないでおく !



2

2016年の初めの時点で、私にとって次の構文はjQuery1.12.0で機能します。

  • IE 11(11.0.9600.18204、アップデート11.0.28、KB3134815): .find("z\\:row")
  • Firefox 44.0.2: .find("z\\:row")
  • Chrome 44.0.2403.89m: .find("row")

この構文.find("[nodeName=z:row]")は、上記のどのブラウザでも機能しません。Chromeで名前空間を適用する方法が見つかりませんでした。

すべてをまとめると、次の構文は上記のすべてのブラウザーで機能します。 .find("row,z\\:row")


1

上記のように、jQueryの現在のブラウザー/バージョンでは上記のソリューションに問題があります-大文字と小文字の問題のために、提案されたプラグインも完全には機能しません(nodeNameプロパティとして、すべて大文字である場合があります)。そこで、次のクイック関数を作成しました。

$.findNS = function (o, nodeName)
{
    return o.children().filter(function ()
    {
        if (this.nodeName)
            return this.nodeName.toUpperCase() == nodeName.toUpperCase();
        else
            return false;
    });
};

使用例:

$.findNS($(xml), 'x:row');

jQueryバージョンの問題を考えると、これは明らかに最良の解決策です
MatteoSp 2013年



0

JQueryを使用してXMLを解析するためのドキュメントを見たことがありません。JQueryは通常、ブラウザdomを使用してHTMLドキュメントを参照しますが、html自体を読み取るとは思いません。

おそらく、JavaScript自体に組み込まれているXML処理を確認する必要があります。

http://www.webreference.com/programming/javascript/definitive2/


3
完全に同意しません。jQueryを使用すると、応答XMLの処理が簡単になります。発生する唯一の問題は、xml名前空間の使用です。
リチャードクレイトン

1
@Richard:Ajaxを使用する場合、jQueryはresponseXML組み込みXMLHttpRequestオブジェクトのプロパティを使用します。これは実際にはXMLドキュメントです。ただし、jQuery(1.5parseXMLが導入されるまで)にはXMLを解析する方法がなかったため、Chrisは正しかった。
ティムダウン

0

名前空間を空の文字列に置き換えただけです。私にとってはうまくいきます。ブラウザ間でテスト済みのソリューション:Firefox、IE、Chrome

私の仕事は、Sharepoint EXCEL RESTAPIを介してEXCELファイルを読み取って解析することでした。XML応答には、「x:」名前空間のタグが含まれています。

XMLの名前空間を空の文字列に置き換えることにしました。次のように機能します。1。XML応答から目的のノードを取得します。2。選択したノードをXML応答(ドキュメント)から文字列に変換します。2。名前空間を空の文字列に置き換えます。3。文字列をXMLドキュメントに変換し直します。

ここでコードの概要を参照してください->

function processXMLResponse)(xData)
{
  var xml = TOOLS.convertXMLToString("", "",$(xData).find("entry content")[0]);
  xml = xml.replace(/x:/g, "");            // replace all occurences of namespace
  xData =  TOOLS.createXMLDocument(xml);   // convert string back to XML
}

XMLから文字列への変換については、ここで解決策を見つけてください:http//www.sencha.com/forum/showthread.php? 34553-Convert-DOM-XML-Document-to-string


0

または、プロジェクトでfast-xml-parserを使用して、XMLデータをJS / JSONオブジェクトに変換することもできます。次に、それをオブジェクトプロパティとして使用できます。JQueryやその他のライブラリは使用しませんが、目的は解決します。

var xmlData = '<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">'
+'   <s:Schema id="RowsetSchema">'
+'     <s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">'
+'       <s:AttributeType name="ows_ID" rs:name="ID" rs:number="1">'
+'        <s:datatype dt:type="i4" dt:maxLength="4" />'
+'      </s:AttributeType>'
+'       <s:AttributeType name="ows_DocIcon" rs:name="Type" rs:number="2">'
+'        <s:datatype dt:type="string" dt:maxLength="512" />'
+'      </s:AttributeType>'
+'       <s:AttributeType name="ows_LinkTitle" rs:name="Title" rs:number="3">'
+'        <s:datatype dt:type="string" dt:maxLength="512" />'
+'      </s:AttributeType>'
+'       <s:AttributeType name="ows_ServiceCategory" rs:name="Service Category" rs:number="4">'
+'        <s:datatype dt:type="string" dt:maxLength="512" />'
+'      </s:AttributeType>'
+'    </s:ElementType>'
+'  </s:Schema>'
+'   <rs:data>'
+'    <z:row ows_ID="2" ows_LinkTitle="Sample Data 1" />'
+'    <z:row ows_ID="3" ows_LinkTitle="Sample Data 2" />'
+'    <z:row ows_ID="4" ows_LinkTitle="Sample Data 3" />'
+'  </rs:data>'
+'</xml>'

var jsObj = parser.parse(xmlData,{attrPrefix:"",ignoreTextNodeAttr: false});
document.write(JSON.stringify(jsObj.xml["rs:data"]["z:row"][0],null,4) + "<br>");
document.write(JSON.stringify(jsObj.xml["rs:data"]["z:row"][1],null,4) + "<br>");
document.write(JSON.stringify(jsObj.xml["rs:data"]["z:row"][2],null,4) + "<br>");
<script src="https://cdnjs.cloudflare.com/ajax/libs/fast-xml-parser/2.9.2/parser.min.js"></script>

js / jsonオブジェクトの解析中は、名前空間を無視できます。この場合、として直接アクセスできますjsObj.xml.data.row

for(var i=0; i< jsObj.xml.data.row.length; i++){
  console.log(jsObj.xml.data.row[i]);
}

免責事項:私はfast-xml-parserを作成しました。


-1

Webkitブラウザーの場合、コロンを省略できます。したがって<media:content>、たとえばRSSフィードで見つけるには、次のようにします。

$(this).find("content");

最新のサファリでは、使用法をサポートしていません。以前のバージョンでのみ機能します。
バリオンリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.