Розбір XML змінної рядка в JavaScript


204

У мене є змінний рядок, який містить добре сформований та дійсний XML. Мені потрібно використовувати JavaScript-код для розбору цього каналу.

Як я можу це зробити за допомогою JavaScript-сумісного коду?

Відповіді:


90

Оновлення: для більш правильної відповіді див. Відповідь Тіма Дауна .

Internet Explorer і, наприклад, браузери на базі Mozilla відкривають різні об'єкти для розбору XML, тому розумно використовувати рамку JavaScript, як jQuery, для обробки відмінностей між перехресними браузерами.

Справді основний приклад:

var xml = "<music><album>Beethoven</album></music>";

var result = $(xml).find("album").text();

Примітка: Як зазначено в коментарях; jQuery насправді не робить жодного аналізу XML, він покладається на метод DOM innerHTML і буде аналізувати його, як і будь-який HTML, тому будьте обережні при використанні імен HTML елементів у вашому XML. Але я думаю, що це працює досить добре для простого "розбору" XML, але, мабуть, не пропонується для інтенсивного чи "динамічного" розбору XML, де ви не заздалегідь наперед, що XML зійде, і це тести, якщо все розбирається, як очікувалося.


6
Код для усунення різниці в синтаксичному аналізі XML між IE та іншими браузерами - це декілька тривіальних рядків, тому не варто підкреслювати 50K jQuery для самостійно. Маніпуляція отриманим XML DOM - інша справа.
Тим Даун

7
І що я не усвідомлював під час публікації попереднього коментаря, це те, що jQuery навіть не розбирає XML, він просто призначає його як innerHTMLвластивість елемента, що зовсім не є надійним.
Тім Даун

Зауважте, що JQuery не підтримує простори імен XML. Дивіться zachleat.com/web/2008/05/10/selecting-xml-with-javascript
mikemaccana

10
Ця відповідь неправильна. Див stackoverflow.com/questions/2124924 / ... , stackoverflow.com/questions/2908899 / ... , відповідь @ Тім Дауна і сам Jquery документації , де говориться: «Зверніть увагу , що [ jQuery()] розбирає HTML, а НЕ XML»
Crescent Fresh

2
@SanderVersluys: оскільки автор не приймає іншої відповіді, я б включив у вашу відповідь примітку, що посилається на правильну відповідь @ TimDown . Таким чином людям не потрібно читати всі ці коментарі, щоб зрозуміти правильну відповідь.
Розсудливий

321

Оновлена ​​відповідь за 2017 рік

Далі буде проаналізовано рядок XML у документі XML у всіх основних браузерах. Якщо вам не потрібна підтримка IE <= 8 або якийсь незрозумілий браузер, ви можете використовувати таку функцію:

function parseXml(xmlStr) {
   return new window.DOMParser().parseFromString(xmlStr, "text/xml");
}

Якщо вам потрібно підтримати IE <= 8, робота виконає наступне:

var parseXml;

if (typeof window.DOMParser != "undefined") {
    parseXml = function(xmlStr) {
        return new window.DOMParser().parseFromString(xmlStr, "text/xml");
    };
} else if (typeof window.ActiveXObject != "undefined" &&
       new window.ActiveXObject("Microsoft.XMLDOM")) {
    parseXml = function(xmlStr) {
        var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async = "false";
        xmlDoc.loadXML(xmlStr);
        return xmlDoc;
    };
} else {
    throw new Error("No XML parser found");
}

Коли ви Documentотримаєте за допомогою parseXml, ви можете використовувати звичайні методи / властивості обходу DOM, такі як childNodesта getElementsByTagName()отримати потрібні вузли.

Приклад використання:

var xml = parseXml("<foo>Stuff</foo>");
alert(xml.documentElement.nodeName);

Якщо ви використовуєте jQuery, з версії 1.5 ви можете використовувати його вбудований parseXML()метод, який функціонально ідентичний вищевказаній функції.

var xml = $.parseXML("<foo>Stuff</foo>");
alert(xml.documentElement.nodeName);

56
Я згоден, на це слід прийняти відповідь. Моя відповідь настільки стара з перших днів, що мені завжди цікаво, що вона все ще отримує відгуки. Хтось підтримує видалення моєї прийнятої відповіді? І чи є недоліком система голосування? Оголосити цього народу!
Сандер Верслуйс

@SanderVersluys: Чи можете ви видалити свою відповідь?
Вітман

1
Довелося вас оскаржити, сказавши, що "інших гідних відповідей немає". Відповідь @SanderVersluys в моєму випадку прекрасно спрацювала. Чого в цьому не гідно, я не знаю.
eric

2
@EricTurner: Я стою на цьому, і сам Сандер відмовився від своєї відповіді. JQuery документи сказати вам не використовувати $()для XML розбору . Читайте коментарі уважніше: у багатьох ситуаціях це просто не працює.
Tim Down

1
@DWoldrich: Я бачив це в обох напрямках в Інтернеті, і підозрюю, що він працює обома способами. Найбільш близькою, яку я можу знайти авторитетною відповіддю, є msdn.microsoft.com/en-us/library/ms761398(v=vs.85).aspx , в якій сказано, що слід використовувати булеву форму. Однак, і скільки значення ви приділяєте цьому, повністю залежить від вас, метод jQueryparseXML() використовує рядок. Я трохи насторожено змінюю відповідь, тому що у мене немає простого способу перевірити її зараз.
Tim Down

19

Більшість прикладів в Інтернеті (а також деякі представлені вище) показують, як завантажити XML з файлу в сумісному режимі браузера. Це доводиться легко, за винятком випадку Google Chrome, який не підтримує document.implementation.createDocument()метод. Під час використання Chrome для завантаження XML-файлу в об'єкт XmlDocument вам потрібно використовувати вбудований об'єкт XmlHttp, а потім завантажити файл, передаючи його URI.

У вашому випадку сценарій інший, тому що ви хочете завантажити XML зі змінної рядка , а не з URL-адреси. Однак для цієї вимоги Chrome нібито працює так само, як Mozilla (або я так чув) і підтримує метод parseFromString ().

Ось функція, яку я використовую (це частина бібліотеки сумісності браузера, яку я зараз будую):

function LoadXMLString(xmlString)
{
  // ObjectExists checks if the passed parameter is not null.
  // isString (as the name suggests) checks if the type is a valid string.
  if (ObjectExists(xmlString) && isString(xmlString))
  {
    var xDoc;
    // The GetBrowserType function returns a 2-letter code representing
    // ...the type of browser.
    var bType = GetBrowserType();

    switch(bType)
    {
      case "ie":
        // This actually calls into a function that returns a DOMDocument 
        // on the basis of the MSXML version installed.
        // Simplified here for illustration.
        xDoc = new ActiveXObject("MSXML2.DOMDocument")
        xDoc.async = false;
        xDoc.loadXML(xmlString);
        break;
      default:
        var dp = new DOMParser();
        xDoc = dp.parseFromString(xmlString, "text/xml");
        break;
    }
    return xDoc;
  }
  else
    return null;
}

16
Мені відомі суперечливі думки щодо нюху браузера, і саме тому я тут не включив цю функцію. Однак не було встановлено, що це НЕПРАВНО. У будь-якому випадку, це навіюючий приклад.
Церебрус

1
Я вважаю, що це неправильно в тому, що ви не можете гарантувати, що це правильно. Будь-хто може підробити рядки UA, і сумнівно, що КОЖЕН браузер, який не є IE, підтримує DOMParser і що ваш нюхальний веб-переглядач є ДОПУСКАНО. І до того ж, це набагато простіше зробити це правильно:if(window.ActiveXObject){...}
1j01

Отже, зараз IE9 + підтримує DOMParser , як ви це будете підтримувати? -1 для того, що говорить @ 1j01. Все, що вам потрібно перевірити - це var dp; try{ dp = new DOMParser() } catch(e) { }; if(dp) { // DOMParser supported } else { // alert('you need to consider upgrading your browser\nOr pay extra money so developer can support the old versions using browser sniffing (eww)') }.
Енні

13

Marknote - це приємний легкий крос-браузер JavaScript XML-аналізатор. Він орієнтований на об'єкти і має безліч прикладів, плюс API задокументовано. Він досить новий, але він добре працював в одному з моїх проектів до цих пір. Мені подобається одне, що він буде читати XML безпосередньо з рядків або URL-адрес, а також ви можете використовувати його для перетворення XML в JSON.

Ось приклад того, що можна зробити з Marknote:

var str = '<books>' +
          '  <book title="A Tale of Two Cities"/>' +
          '  <book title="1984"/>' +
          '</books>';

var parser = new marknote.Parser();
var doc = parser.parse(str);

var bookEls = doc.getRootElement().getChildElements();

for (var i=0; i<bookEls.length; i++) {
    var bookEl = bookEls[i];
    // alerts "Element name is 'book' and book title is '...'"
    alert("Element name is '" + bookEl.getName() + 
        "' and book title is '" + 
        bookEl.getAttributeValue("title") + "'"
    );
}

Здається, Marknote реалізує чистий аналізатор JavaScript. Це означає, що він повинен бути сумісним з будь-яким механізмом javascript, де б він не використовувався в браузері, в node.js або в автономному механізмі javascript ...
Coyote

8

Я завжди використовував підхід, під яким працює IE та Firefox.

Приклад XML:

<fruits>
  <fruit name="Apple" colour="Green" />
  <fruit name="Banana" colour="Yellow" />
</fruits>

JavaScript:

function getFruits(xml) {
  var fruits = xml.getElementsByTagName("fruits")[0];
  if (fruits) {
    var fruitsNodes = fruits.childNodes;
    if (fruitsNodes) {
      for (var i = 0; i < fruitsNodes.length; i++) {
        var name = fruitsNodes[i].getAttribute("name");
        var colour = fruitsNodes[i].getAttribute("colour");
        alert("Fruit " + name + " is coloured " + colour);
      }
    }
  }
}

Як би ви сприйняли цінність, якщо б у вас була ситуація <fruit> значення </fruit>?
Сібля

1
@Siblja innerTextзамість васgetAttribute()
Manux22


2

Погляньте на XML DOM Parser ( W3Schools ). Це підручник з розбору XML DOM. Фактичний аналізатор DOM відрізняється від браузера до браузера, але API DOM є стандартизованим і залишається таким же (більш-менш).

Як варіант, використовуйте E4X, якщо ви можете обмежитися Firefox. Це порівняно простіше у використанні, і він є частиною JavaScript з версії 1.6. Ось невеликий зразок використання ...

//Using E4X
var xmlDoc=new XML();
xmlDoc.load("note.xml");
document.write(xmlDoc.body); //Note: 'body' is actually a tag in note.xml,
//but it can be accessed as if it were a regular property of xmlDoc.

0
<script language="JavaScript">
function importXML()
{
    if (document.implementation && document.implementation.createDocument)
    {
            xmlDoc = document.implementation.createDocument("", "", null);
            xmlDoc.onload = createTable;
    }
    else if (window.ActiveXObject)
    {
            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.onreadystatechange = function () {
                    if (xmlDoc.readyState == 4) createTable()
            };
    }
    else
    {
            alert('Your browser can\'t handle this script');
            return;
    }
    xmlDoc.load("emperors.xml");
}

function createTable()
{
    var theData="";
    var x = xmlDoc.getElementsByTagName('emperor');
    var newEl = document.createElement('TABLE');
    newEl.setAttribute('cellPadding',3);
    newEl.setAttribute('cellSpacing',0);
    newEl.setAttribute('border',1);
    var tmp = document.createElement('TBODY');
    newEl.appendChild(tmp);
    var row = document.createElement('TR');
    for (j=0;j<x[0].childNodes.length;j++)
    {
            if (x[0].childNodes[j].nodeType != 1) continue;
            var container = document.createElement('TH');
            theData = document.createTextNode(x[0].childNodes[j].nodeName);
            container.appendChild(theData);
            row.appendChild(container);
    }
    tmp.appendChild(row);
    for (i=0;i<x.length;i++)
    {
            var row = document.createElement('TR');
            for (j=0;j<x[i].childNodes.length;j++)
            {
                    if (x[i].childNodes[j].nodeType != 1) continue;
                    var container = document.createElement('TD');
                    var theData = document.createTextNode(x[i].childNodes[j].firstChild.nodeValue);
                    container.appendChild(theData);
                    row.appendChild(container);
            }
            tmp.appendChild(row);
    }
    document.getElementById('writeroot').appendChild(newEl);
}
</script>
</HEAD>

<BODY onLoad="javascript:importXML();">
<p id=writeroot> </p>
</BODY>

Для отримання додаткової інформації зверніться до цього http://www.easycodingclub.com/xml-parser-in-javascript/javascript-tutorials/


0

Відмова : Я створив швидкий аналізатор xml

Я створив швидкий синтаксичний аналізатор для аналізу XML-рядка в JS / JSON-об'єкт або проміжний обхідний об'єкт. Очікується, що вона буде сумісною у всіх браузерах (проте протестована лише на Chrome, Firefox та IE).

Використання

var options = { //default
    attrPrefix : "@_",
    attrNodeName: false,
    textNodeName : "#text",
    ignoreNonTextNodeAttr : true,
    ignoreTextNodeAttr : true,
    ignoreNameSpace : true,
    ignoreRootElement : false,
    textNodeConversion : true,
    textAttrConversion : false,
    arrayMode : false
};

if(parser.validate(xmlData)){//optional
    var jsonObj = parser.parse(xmlData, options);
}

//Intermediate obj
var tObj = parser.getTraversalObj(xmlData,options);
:
var jsonObj = parser.convertToJson(tObj);

Примітка . Він не використовує аналізатор DOM, але розбирає рядок за допомогою RE і перетворює його в об'єкт JS / JSON.

Спробуйте в Інтернеті , CDN


-1

Ви також можете за допомогою функції jquery ($. ParseXML) маніпулювати рядком xml

приклад javascript:

var xmlString = '<languages><language name="c"></language><language name="php"></language></languages>';
var xmlDoc = $.parseXML(xmlString);
$(xmlDoc).find('name').each(function(){
    console.log('name:'+$(this).attr('name'))
})
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.