2015-07-16 3 views
2

Я пытаюсь использовать XSL для перевода XML-файла в аккуратную таблицу. Для этого я использовал примеры, предоставленные W3schools, которые можно найти в качестве отправной точки here. Тем не менее браузер (хром) бросает ошибку, описанную в заголовке этого сообщения. Я даже попытался скопировать тот же самый пример на W3, чтобы его можно было встретить с той же ошибкой. Пробовал отладки в Firefox, это вывод на консоль
TypeError: Argument 1 of XSLTProcessor.importStylesheet is not an object.Uncaught TypeError: Не удалось выполнить 'importStylesheet' в 'XSLTProcessor': параметр 1 не имеет тип 'Node'

Аналогичный вопрос был опубликован раньше, и решение было в изменении модели от синхронны ASync. Я попытался сделать это с помощью метода onreadystatechange, но безуспешно. Вот код, с которым я работал.

<html> 
<head> 
<script> 
    function loadXMLDoc(filename) 
    { 
    if (window.ActiveXObject) 
     { 
     xhttp = new ActiveXObject("Msxml2.XMLHTTP"); 
     } 
    else 
     { 
     xhttp = new XMLHttpRequest(); 
     } 
    xhttp.onreadystatechange = function() { 
     if (xhttp.readyState == 4 && xhttp.status == 200) { 
     return xhttp.responseXML; 
     } 
    }; 
    xhttp.open("GET", filename); 
    try {xhttp.responseType = "msxml-document"} catch(err) {} // Helping IE11 
    xhttp.send(""); 
    } 

    function displayResult() 
    { 
    xsl = loadXMLDoc("cdcatalog.xsl"); 
    xml = loadXMLDoc("cdcatalog.xml"); 
    // code for IE 
    if (window.ActiveXObject || xhttp.responseType == "msxml-document") 
     { 
     ex = xml.transformNode(xsl); 
     document.getElementById("dataTable").innerHTML = ex; 
     } 
    // code for Chrome, Firefox, Opera, etc. 
    else if (document.implementation && document.implementation.createDocument) 
     { 
     xsltProcessor = new XSLTProcessor(); 
     xsltProcessor.importStylesheet(xsl); 
     resultDocument = xsltProcessor.transformToFragment(xml, document); 
     document.getElementById("dataTable").appendChild(resultDocument); 
     } 
    } 
</script> 
</head> 
<body onload="displayResult()"> 
<div id="dataTable" /> 
</body> 

Спасибо за помощь!

+0

Если вы хотите использовать асинхронный XMLHttpRequest, вам нужно поместить обработку кода и использовать 'responseXML' в обработчик события или хотя бы вызвать его из обработчика события. –

+0

Нет, используйте синхронную загрузку ('xhttp.open (« GET », filename, false);'), как это сделано в примере, к которому вы привязались, или убедитесь, что вы используете 'onreadystatehandler' для работы с responseXML. –

+0

Благодарим вас за ответ Martin. Основываясь на вашем комментарии, я написал этот код 'xhr = new XMLHttpRequest(); \t xhr.onreadystatechange = функция() { \t \t, если (xhr.status == 200 && xhr.readyState == 4) { \t \t \t возвращение xhr.responseXML; \t \t} \t} \t xhr.open ("GET", fileName); \t xhr.send (""); ' Я повторно проанализировал код для использования модели синхронизации, но без обработчиков событий, и он сработал. Однако противоположное утверждение неверно, чтобы использовать асинхронную модель, но с обработчиками событий. Код выше - моя попытка. Мои пристрастия к форматированию, я много раз пытался блокировать его формат, и он не работал. – Cristiansen

ответ

0

Ниже приведен пример двух асинхронных запросов, в которых обратный вызов одного обработчика событий запускает следующий запрос, обратный вызов которого делает преобразование. Чтобы это было просто, я использовал onload вместо onreadystatechange, если вам действительно нужна поддержка старых версий IE, вам нужно будет адаптировать код.

<!DOCTYPE html> 
<html> 
<head> 
<meta charset="UTF-8"> 
<title>XMLHttpRequest and onload handler with asynchronous requests</title> 
<script> 
function load(url, callback) { 
    var req = new XMLHttpRequest(); 
    req.open('GET', url); 
    // to allow us doing XSLT in IE 
    try { req.responseType = "msxml-document" } catch (ex) {} 
    req.onload = function() { 
    callback(req.responseXML); 
    }; 
    req.send(); 
} 

function transform(xml, xsl) { 
    load(
    xml, 
    function(inputXml) { 
     load(
     xsl, 
     function(xsltSheet) { 
      displayResult(inputXml, xsltSheet); 
     } 
    ); 
    } 
); 
} 

function displayResult(xmlInput, xsltSheet) { 
    if (typeof XSLTProcessor !== 'undefined') { 
    var proc = new XSLTProcessor(); 
    proc.importStylesheet(xsltSheet); 
    document.getElementById('example').appendChild(proc.transformToFragment(xmlInput, document)); 
    } 
    else if (typeof xmlInput.transformNode !== 'undefined') { 
    document.getElementById("example").innerHTML = xmlInput.transformNode(xsltSheet); 
    } 
} 
</script> 
</head> 
    <body onload="transform('catalog.xml', 'catalog.xsl')"> 
<div id="example"></div> 
</body> 
</html> 

Интернет на http://home.arcor.de/martin.honnen/xslt/test2015072001.html, отлично работает с текущими версиями IE, Firefox и Chrome на Windows, 8.1.

Если вы хотите, чтобы начать два асинхронных запросов непосредственно для загрузки XML и XSLT, то вам нужно сделать немного больше работы, чтобы убедиться, что вы знаете, когда оба документа были загружены для их обработки, пример того, что находится в http://home.arcor.de/martin.honnen/xslt/test2015072101.html:

<!DOCTYPE html> 
<html> 
<head> 
<meta charset="UTF-8"> 
<title>XMLHttpRequest and onload handler with asynchronous requests</title> 
<script> 
function makeRequest(url, loadedData, property, elementToAddResult) { 
    var req = new XMLHttpRequest(); 
    req.open('GET', url); 
    // to allow us doing XSLT in IE 
    try { req.responseType = "msxml-document" } catch (ex) {} 
    req.onload = function() { 
    loadedData[property] = req.responseXML; 
    if (checkLoaded(loadedData)) { 
     displayResult(loadedData.xmlInput, loadedData.xsltSheet, elementToAddResult); 
    }; 
    }; 
    req.send(); 
} 

function checkLoaded(loadedData) { 
    return loadedData.xmlInput != null && loadedData.xsltSheet != null; 
} 

function loadAndTransform(xml, xsl, elementToAddResult) { 
    var loadedData = { xmlInput: null, xsltSheet: null }; 

    makeRequest(xml, loadedData, 'xmlInput', elementToAddResult); 
    makeRequest(xsl, loadedData, 'xsltSheet', elementToAddResult); 
} 

function displayResult(xmlInput, xsltSheet, elementToAddResult) { 
    if (typeof XSLTProcessor !== 'undefined') { 
    var proc = new XSLTProcessor(); 
    proc.importStylesheet(xsltSheet); 
    elementToAddResult.appendChild(proc.transformToFragment(xmlInput, document)); 
    } 
    else if (typeof xmlInput.transformNode !== 'undefined') { 
    elementToAddResult.innerHTML = xmlInput.transformNode(xsltSheet); 
    } 
} 
</script> 
</head> 
    <body onload="loadAndTransform('catalog.xml', 'catalog.xsl', document.getElementById('example'));"> 
<div id="example"></div> 
</body> 
</html> 
+0

Спасибо, Мартин очень. Я все еще перевариваю предоставленную вами информацию. Более того, концепция обратных вызовов. Я новичок в программировании в целом. Когда я пойму код, который вы предоставили, я отправлю больше вопросов. Я просто хотел поблагодарить вас за помощь. – Cristiansen

+0

Есть что-то, что я нашел странным при работе с кодом. Если в браузере есть большой кеш, я бы получил ошибку «аргумент 1 из XSLTP.importStylesheet не имеет тип« Node ». Если я очищу кеш, все работает чудесно. Есть ли объяснение этому? Спасибо – Cristiansen

+0

Ну любой запрос браузера может быть загружен из его кеша, будь то ссылка или что-то сделано со скриптом и XMLHttpRequest. И если в какой-то момент загруженный файл не был даже хорошо сформированным XML-документом, тогда, в зависимости от браузера, 'responseXML' может быть нулевым. –

Смежные вопросы