Jestem nowy w jQuery i chciałbym przeanalizować dokument XML.
Jestem w stanie przeanalizować zwykły XML z domyślnymi przestrzeniami nazw, ale z XML, takimi jak:
<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>
Wszystko, czego naprawdę chcę, to <z:row>
.
Do tej pory używałem:
$.get(xmlPath, {}, function(xml) {
$("rs:data", xml).find("z:row").each(function(i) {
alert("found zrow");
});
}, "xml");
bez powodzenia. Jakieś pomysły?
javascript
jquery
xml
namespaces
xsd
Brian Liang
źródło
źródło
Odpowiedzi:
Mam to.
Okazuje się, że wymaga
\\
ucieczki z okrężnicy.$.get(xmlPath, {}, function(xml) { $("rs\\:data", xml).find("z\\:row").each(function(i) { alert("found zrow"); }); }, "xml");
Jak wskazał Rich:
Lepsze rozwiązanie nie wymaga ucieczki i działa na wszystkich "nowoczesnych" przeglądarkach:
.find("[nodeName=z:row]")
źródło
$('[nodeName=rs:data]', xml).find('[nodeName=z:row]')
- działa z 1.3.2 pod WebKitem (gdzie metoda ucieczki dwukropka najwyraźniej nie działa)$('[nodeName=rs:data],data')
rs
,dt
czys
nie są naprawdę nazw. Przestrzenie nazw to URN w górnej części pliku. Przedrostki to po prostu aliasy wybrane przez autora dokumentu, aby zachować zwięzłość. Ten sam dokument, pasujący do tych samych przestrzeni nazw, można utworzyć z zupełnie różnymi prefiksami. Zachęcam wszystkich do szukania interfejsów API, które rozumieją przestrzenie nazw, zamiast zakładać prefiksy w zapytaniach. Np. W przeglądarce DOM API możesz używaćgetElementByTagNameNS()
igetAttributeNS()
.Spędziłem kilka godzin na czytaniu o wtyczkach i wszelkiego rodzaju rozwiązaniach bez powodzenia.
ArnisAndy opublikował łącze do dyskusji jQuery, w której jest oferowana ta odpowiedź i mogę potwierdzić, że działa to dla mnie w Chrome (wersja 18.0), FireFox (wersja 11.0), IE (wersja 9.08) i Safari (wersja 5.1.5) ) przy użyciu jQuery (v1.7.2).
Próbuję zeskrobać kanał WordPress, w którym zawartość nosi nazwę <content: encoded> i to właśnie zadziałało:
content: $this.find("content\\:encoded, encoded").text()
źródło
.each()
pętli do iteracjęitem
elementów:$('dc\\:creator, creator', this).text()
. Chociaż nie jestem pewien, dlaczego ten dodatek, creator
był potrzebny idc\\:creator
nie tylko działał.Jeśli używasz jquery 1.5, będziesz musiał dodać cudzysłowy wokół wartości atrybutu selektora węzła, aby działało:
.find('[nodeName="z:row"]')
źródło
Chociaż powyższa odpowiedź wydaje się być poprawna, nie działa ona w przeglądarkach webkit (Safari, Chrome). Uważam, że lepszym rozwiązaniem byłoby:
.find("[nodeName=z:myRow, myRow]")
źródło
$('[nodeName=rs:data],data')
Na wypadek, gdyby ktoś musiał to zrobić bez jQuery , tylko z normalnym Javascriptem i dla Google Chrome (webkit) , jest to jedyny sposób, w jaki udało mi się go uruchomić po wielu badaniach i testach.
Że będzie pracować dla pobierania następujący węzeł:
<prefix:name>
. Jak widać, przedrostek lub przestrzeń nazw są pomijane i będą dopasowywać elementy z różnymi przestrzeniami nazw pod warunkiem, że nazwa znacznika toname
. Ale miejmy nadzieję, że nie będzie to dla ciebie problemem.Nic z tego nie zadziałało (rozwijam rozszerzenie Google Chrome):
getElementsByTagNameNS("prefix", "name")
getElementsByTagName("prefix:name")
getElementsByTagName("prefix\\:name")
getElementsByTagName("name")
Edycja : po pewnym śnie znalazłem działające obejście :) Ta funkcja zwraca pierwszy węzeł pasujący do pełnego, na
nodeName
przykład<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; }
Można go łatwo zmodyfikować w przypadku konieczności zwrócenia wszystkich pasujących elementów. Mam nadzieję, że to pomoże!
źródło
Żadne z powyższych rozwiązań nie działa tak dobrze. Znalazłem to i poprawiono szybkość. po prostu dodaj to, działało jak urok:
$.fn.filterNode = function(name) { return this.find('*').filter(function() { return this.nodeName === name; }); };
stosowanie:
var ineedthatelementwiththepsuedo = $('someparentelement').filterNode('dc:creator');
źródło: http://www.steveworkman.com/html5-2/javascript/2011/improving-javascript-xml-node-finding-performance-by-2000/
źródło
Ucieczka „\\” nie jest niezawodna i prosta
.find('[nodeName="z:row"]')
Wydaje się, że metoda została złamana w Jquery 1.7. Udało mi się znaleźć rozwiązanie dla 1.7, używając funkcji filtru, tutaj: Poprawa wydajności wyszukiwania węzłów JavaScript XML
źródło
Warto zauważyć, że od wersji jQuery 1.7 występowały problemy z niektórymi obejściami dotyczącymi znajdowania elementów w przestrzeni nazw. Zobacz te linki, aby uzyskać więcej informacji:
źródło
Znalezione rozwiązanie w komentarzu: Parsowanie XML z przestrzeniami nazw za pomocą jQuery $ (). Find
Moja konfiguracja:
Przykładowy kod XML (fragment z interfejsu API Kontaktów Google):
<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 protected]" primary="true"/> </entry>
Kod parsowania:
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
źródło
jQuery 1.7 nie działa z następującymi elementami:
$(xml).find("[nodeName=a:IndexField2]")
Jednym z rozwiązań, które udało mi się pracować w Chrome, Firefox i IE, jest użycie selektorów, które działają w IE ORAZ selektory, które działają w Chrome, w oparciu o fakt, że jeden sposób działa w IE, a drugi w Chrome:
$(xml).find('a\\\\:IndexField2, IndexField2')
W IE zwraca to węzły przy użyciu przestrzeni nazw (Firefox i IE wymagają przestrzeni nazw), aw przeglądarce Chrome selektor zwraca węzły na podstawie selektora innego niż przestrzeń nazw. Nie testowałem tego w Safari, ale powinno działać, ponieważ działa w Chrome.
źródło
Moim rozwiązaniem (ponieważ używam proxy PHP) jest zastąpienie: przestrzeń nazw przez _ ... więc koniec problemów z przestrzenią nazw ;-)
Nie komplikuj !
źródło
Oryginalna odpowiedź: jQuery XML parsing jak uzyskać atrybut elementu
Oto przykład, jak skutecznie uzyskać wartość w przeglądarce Chrome.
item.description = jQuery(this).find("[nodeName=itunes\\:summary]").eq(0).text();
źródło
Od początku 2016 r. Dla mnie z jQuery 1.12.0 działa następująca składnia:
.find("z\\:row")
.find("z\\:row")
.find("row")
Składnia
.find("[nodeName=z:row]")
nie działa w żadnej z wyżej wymienionych przeglądarek. Nie znalazłem sposobu na zastosowanie przestrzeni nazw w Chrome.Podsumowując, następująca składnia działa we wszystkich wymienionych powyżej przeglądarkach:
.find("row,z\\:row")
źródło
Jak wspomniano powyżej, istnieją problemy z powyższym rozwiązaniem w obecnych przeglądarkach / wersjach jQuery - sugerowana wtyczka nie działa całkowicie z powodu problemów z wielkością liter (
nodeName
jako właściwość czasami jest pisana wielkimi literami). Tak więc napisałem następującą szybką funkcję:$.findNS = function (o, nodeName) { return o.children().filter(function () { if (this.nodeName) return this.nodeName.toUpperCase() == nodeName.toUpperCase(); else return false; }); };
Przykładowe użycie:
$.findNS($(xml), 'x:row');
źródło
zadowolony:
$this.find("content\\:encoded, encoded").text()
to idealne rozwiązanie ...
źródło
Istnieje wtyczka jquery-xmlns dla jQuery do pracy z przestrzeniami nazw w selektorach.
źródło
Nie widziałem żadnej dokumentacji dotyczącej używania JQuery do analizowania XML. JQuery zwykle używa domeny przeglądarki do przeglądania dokumentu HTML, nie sądzę, aby czyta ona sam html.
Prawdopodobnie powinieneś spojrzeć na wbudowaną obsługę XML w samym JavaScript.
http://www.webreference.com/programming/javascript/definitive2/
źródło
responseXML
właściwości wbudowanegoXMLHttpRequest
obiektu, który w rzeczywistości jest dokumentem XML. Jednak jQuery (do 1.5, kiedyparseXML
został wprowadzony) nie miał możliwości analizowania XML, więc Chris miał rację.właśnie zastąpiłem przestrzeń nazw pustym ciągiem. U mnie działa dobrze. Testowane rozwiązanie w różnych przeglądarkach: Firefox, IE, Chrome
Moim zadaniem było odczytanie i przeanalizowanie pliku EXCEL przez Sharepoint EXCEL REST API. Odpowiedź XML zawiera tagi z przestrzenią nazw „x:”.
Postanowiłem zastąpić przestrzeń nazw w XML-u pustym ciągiem. Działa w ten sposób: 1. Pobierz żądany węzeł z odpowiedzi XML 2. Przekształć wybrany węzeł Odpowiedź XML (dokument) na łańcuch 2. Zastąp przestrzeń nazw pustym ciągiem 3. Przekształć ciąg z powrotem na dokument XML
Zobacz zarys kodu tutaj ->
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 }
Rozwiązanie dotyczące konwersji XML na ciąg znaków znajdziesz tutaj: http://www.sencha.com/forum/showthread.php?34553-Convert-DOM-XML-Document-to-string
źródło
Alternatywnie możesz użyć fast-xml-parser w swoim projekcie i przekonwertować dane XML na obiekt JS / JSON. Następnie możesz użyć go jako właściwości obiektu. Nie używa JQuery ani innych bibliotek, ale rozwiąże Twój cel.
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>
Możesz ignorować przestrzenie nazw podczas analizowania do obiektu js / json. W takim przypadku możesz uzyskać bezpośredni dostęp do plików
jsObj.xml.data.row
.for(var i=0; i< jsObj.xml.data.row.length; i++){ console.log(jsObj.xml.data.row[i]); }
Zastrzeżenie : stworzyłem parser fast-xml.
źródło
W przypadku przeglądarek Webkit możesz po prostu pominąć dwukropek. Aby znaleźć
<media:content>
na przykład kanał RSS, możesz zrobić to:$(this).find("content");
źródło