jQuery XML разбор с пространствами имен


Я новичок в 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> ' s.

до сих пор я делал:

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

действительно не повезло. Есть идеи? Спасибо.

20 78

20 ответов:

я понял.

оказывается, что это требует \ чтобы избежать толстой кишки.

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

как указал Рич:

лучшее решение не требует экранирования и работает на всех" современных " браузерах:

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

Я потратил несколько часов на это чтение о плагинах и всевозможных решениях без везения.

ArnisAndy разместил ссылку на jQuery в дискуссии, где этот ответ, и я могу подтвердить, что это работает для меня в Chrome(V18 стоит.0), Firefox(начиная с версии 11.0), т. е.(В9.08) и Safari (версии V5.1.5) с помощью jQuery (версия v1.7.2).

Я пытаюсь очистить ленту WordPress, где контент называется , и это то, что сработало для меня:

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

Если вы используете jquery 1.5, вам придется добавить кавычки вокруг значения атрибута селектора узлов, чтобы заставить его работать:

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

хотя приведенный выше ответ кажется правильным, он не работает в браузерах webkit (Safari, Chrome). Лучшим решением, я считаю, будет:

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

в случае кто-то должен сделать это без jQuery, просто с обычным JavaScript и Google Chrome (webkit), это единственный способ, который я нашел, чтобы заставить его работать после многих исследований и испытаний.

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

это будет работать для получения следующего узла:<prefix:name>. Как вы можете видеть, префикс или пространство имен опущен, и он будет соответствовать элементам с разными пространствами имен при условии, что имя тега name. Но, надеюсь, это не будет проблемой для вас.

ничего из этого не работает для меня (я разрабатываю расширение Google Chrome):

getElementsByTagNameNS("prefix", "name")

getElementsByTagName("prefix:name")

getElementsByTagName("prefix\:name")

getElementsByTagName("name")

Edit: после сна, Я нашел рабочее решение :) эта функция возвращает первый узел, соответствующий полной 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;
}

он может быть легко изменен в случае, если вам нужно вернуть все соответствующие элементы. Надеюсь, это поможет!

ни одно из решений выше, что хорошо. Я нашел это и был улучшен для скорости. просто добавьте это, сработало как шарм:

$.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/

"\ \ " побег не является надежным и простым

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

метод, кажется, был нарушен с Jquery 1.7. Я смог найти решение для 1.7, используя функцию фильтра, здесь:повышение производительности поиска узлов Javascript XML

стоит отметить, что по состоянию на jQuery 1.7 были проблемы с некоторыми обходными путями для поиска элементов пространства имен. Увидеть эти ссылки для получения дополнительной информации:

нашел решение в комментарий: разбор XML с пространствами имен с помощью jQuery $().найти

использование второй половины имени узла после двоеточия работало для меня. Используется .найти ("лат") вместо .найти ("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

jQuery 1.7 не работает со следующим:

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

одно решение, которое я получил для работы в Chrome, Firefox и IE, заключается в использовании селекторов, которые работают в IE, и селекторов, которые работают в Chrome, основываясь на том, что один способ работает в IE, а другой в Chrome:

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

в IE это возвращает узлы, использующие пространство имен (Firefox и IE требуют пространства имен), а в Chrome селектор возвращает узлы на основе селектора без пространства имен. Я не проверял это в Safari, но он должен работать, потому что он работает в Chrome.

мое решение (потому что я использую PHP прокси) заключается в замене : namespace на _ ... так что больше никаких проблем с пространством имен; -)

держите его просто !

Оригинальный Ответ : jQuery XML parsing как получить атрибут элемента

вот пример того, как успешно получить значение в Chrome..

 item.description = jQuery(this).find("[nodeName=itunes\:summary]").eq(0).text();

по состоянию на начало 2016 года, для меня следующий синтаксис работы с jQuery 1.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.89 m:.find("row")

синтаксис .find("[nodeName=z:row]") не работает ни в одном из браузеров, упомянутых выше. Я не нашел способа применить пространство имен в Chrome.

положить все это вместе, следующий синтаксис работает во всех браузеры, упомянутые выше:.find("row,z\:row")

Как упоминалось выше, есть проблемы с вышеуказанным решением с текущими браузерами / версиями jQuery-предлагаемый плагин не полностью работает либо из-за проблем с case (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');

содержание: $this.find("content\:encoded, encoded").text()

является идеальным решением...

есть плагин jquery-xmlns для jQuery для работы с пространствами имен в селекторах.

Я не видел никакой документации по использованию JQuery для разбора XML. JQuery обычно использует браузер dom для просмотра HTML-документа, я не верю, что он читает сам html.

вероятно, вы должны посмотреть на встроенную обработку XML в самом JavaScript.

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

просто заменил пространство пустой строкой. Отлично работает для меня. Протестировано решение в разных браузерах: Firefox, IE, Chrome

моей задачей было прочитать и проанализировать EXCEL-файл через Sharepoint EXCEL REST API. 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

кроме того, вы можете использовать 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]);
}

отказ от ответственности: я создал быстрый XML-парсера.

для браузеров Webkit вы можете просто оставить двоеточие. Так что найти <media:content> в RSS-канал, например, вы можете сделать это:

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