Chrome i Safari XSLT za pomocą JavaScript
Mam następujący kod, który stosuje styl XSLT
Test.Xml.xslTransform = function(xml, xsl) {
try {
// code for IE
if (window.ActiveXObject) {
ex = xml.transformNode(xsl);
return ex;
}
// code for Mozilla, Firefox, Opera, etc.
else if (document.implementation && document.implementation.createDocument) {
xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
resultDocument = xsltProcessor.transformToFragment(xml, document);
return resultDocument;
}
} catch (exception) {
if (typeof (exception) == "object") {
if (exception.message) {
alert(exception.message);
}
} else {
alert(exception);
}
}
Kod działa w IE i Firefoksie, ale nie w Chrome i Safari. Jakieś pomysły dlaczego?
Update
ResultDocument = xsltProcessor.transformToFragment(xml, document);
Powyższa linia zwraca null. Żaden błąd nie jest wyrzucany.
Update
Kod nie działa, ponieważ plik XSLT zawiera xsl: include. Trzeba znaleźć sposób, aby włączyć działa będę wklej postęp tutaj
Update
Zalecono, że używam http://plugins.jquery.com/project/Transform / plugin. Staram się wykorzystać libary po stronie klienta jako przykład prac include ( http://daersystems.com/jquery/transform/).
Kod działa w IE, ale nadal nie w chrome.
Test.Xml.xslTransform = function(xml, xsl) {
try {
$("body").append("<div id='test' style='display:none;'></div>");
var a = $("#test").transform({ xmlobj: xml, xslobj: xsl });
return a.html();
}
catch (exception) {
if (typeof (exception) == "object") {
if (exception.message) {
alert(exception.message);
}
} else {
alert(exception);
}
}
}
Xml i xsl są obiektami przekazywanymi.
Update
Próbowałem zmienić plik XSL na coś bardzo proste bez include I Chrome nadal nie stosuje arkusza stylów i IE jest. XSL, który jest wprowadzany jako obiekt to:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rs="urn:schemas-microsoft-com:rowset"
xmlns:z="#RowsetSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:spsoap="http://schemas.microsoft.com/sharepoint/soap/"
>
<xsl:output method="html"/>
<xsl:template match="/">
<h1>test</h1>
</xsl:template>
</xsl:stylesheet>
Update
Pożądany efekt końcowy to zastosowanie XSL do pliku xml. Plik xsl zawiera w sobie includes. Chcę, aby trasnfer miał miejsce na kliencie.
Aktualizacja Rupert mógłbyś zaktualizować pytanie za pomocą xml i jak nazywasz Test.Xml.xslTransform ?
I Pobierz xml używając ie8
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><SearchListItemsResponse xmlns="http://schemas.microsoft.com/sharepoint/soap/"><SearchListItemsResult><listitems 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">
<rs:data ItemCount="1">
<z:row ows_Title="Test" ows_FirstName="Test 4" ows_UniqueId="74;#{1A16CF3E-524D-4DEF-BE36-68A964CC24DF}" ows_FSObjType="74;#0" ows_MetaInfo="74;#" ows_ID="74" ows_owshiddenversion="10" ows_Created="2009-12-29 12:21:01" ows_FileRef="74;#Lists/My List Name/74_.000" ReadOnly="False" VerificationRequired="0"/>
</rs:data>
</listitems></SearchListItemsResult></SearchListItemsResponse></soap:Body></soap:Envelope>
Kod jest wywoływany w następujący sposób:
xsl = Test.Xml.loadXMLDoc("/_layouts/xsl/xsl.xslt");
var doc = Test.Xml.xslTransform(xData.responseXML, xsl);
XData to xml zwracany przez usługę internetową.
2 answers
Jeśli twój XSLT używa xsl:include
możesz otrzymać dziwne niewytłumaczalne błędy, ale zawsze z tym samym rezultatem końcowym: twoja transformacja zawodzi.
Zobacz ten raport o błędzie chromium i wesprzyj go! http://code.google.com/p/chromium/issues/detail?id=8441
Błąd jest rzeczywiście w webkit choć. Aby uzyskać więcej informacji Oto kolejny link, który idzie bardziej szczegółowo, dlaczego to nie działa.
Jedynym sposobem obejścia tego problemu jest wstępne przetworzenie arkusza stylów tak, że wstrzykuje dołączone arkusze stylów. Czyli to, co biblioteka XSLT crossbrowser jak Sarissa zrobi dla ciebie automatycznie.
Jeśli szukasz rozwiązania jQuery:
http://plugins.jquery.com/project/Transform/ jest wtyczką cross browser xsl. Z powodzeniem wykorzystałem to, aby pracować w przeszłości bez większych kłopotów. Nie musisz przepisywać swojego xsl ta wtyczka wstępnie przetworzy je za Ciebie. Zdecydowanie warto się przyjrzeć, ponieważ jest bardziej lekki niż Sarissa.
UPDATE:
<html>
<head>
<script language="javascript" src="jquery-1.3.2.min.js"></script>
<script language="javascript" src="jquery.transform.js"></script>
<script type="text/javascript">
function loadXML(file)
{
var xmlDoc = null;
try //Internet Explorer
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async=false;
xmlDoc.load(file);
}
catch(e)
{
try //Firefox, Mozilla, Opera, etc.
{
xmlDoc=document.implementation.createDocument("","",null);
xmlDoc.async=false;
xmlDoc.load(file);
}
catch(e)
{
try //Google Chrome
{
var xmlhttp = new window.XMLHttpRequest();
xmlhttp.open("GET",file,false);
xmlhttp.send(null);
xmlDoc = xmlhttp.responseXML.documentElement;
}
catch(e)
{
error=e.message;
}
}
}
return xmlDoc;
}
function xslTransform(xmlObject, xslObject)
{
try
{
$("body").append("<div id='test'></div>");
var a = $("#test").transform({ xmlobj: xmlObject, xslobj: xslObject });
}
catch (exception)
{
if (typeof (exception) == "object" && exception.message)
alert(exception.message);
else alert(exception);
}
}
var xmlObject = loadXML("input.xml");
var xslObject = loadXML("transform.xsl");
$(document).ready(function()
{
xslTransform(xmlObject, xslObject);
});
</script>
</head>
<body>
</body>
</html>
Ta testowa strona html działa zarówno w Chrome / FireFox / IE.
Input.xml jest tylko prostym plikiem xml zawierającym <root />
transformacja.xsl to rozebrany xsl, który opublikowałeś.
EDIT
Wydaje się jednak, że $.transform ma problemy z importowaniem arkuszy stylów z dołączonych plików:
Oto Jak to naprawić:
Zlokalizuj
var safariimportincludefix = function(xObj,rootConfig) {
W jquery.transform.js
i zastąp całą funkcję to:
var safariimportincludefix = function(xObj,rootConfig) {
var vals = $.merge($.makeArray(xObj.getElementsByTagName("import")),$.makeArray(xObj.getElementsByTagName("include")));
for(var x=0;x<vals.length;x++) {
var node = vals[x];
$.ajax({
passData : { node : node, xObj : xObj, rootConfig : rootConfig},
dataType : "xml",
async : false,
url : replaceref(node.getAttribute("href"),rootConfig),
success : function(xhr) {
try {
var _ = this.passData;
xhr = safariimportincludefix(xhr,_.rootConfig);
var imports = $.merge(childNodes(xhr.getElementsByTagName("stylesheet")[0],"param"),childNodes(xhr.getElementsByTagName("stylesheet")[0],"template"));
var excistingNodes = [];
try
{
var sheet = _.xObj;
var params = childNodes(sheet,"param");
var stylesheets = childNodes(sheet,"template");
existingNodes = $.merge(params,stylesheets);
}
catch(exception)
{
var x = exception;
}
var existingNames = [];
var existingMatches = [];
for(var a=0;a<existingNodes.length;a++) {
if(existingNodes[a].getAttribute("name")) {
existingNames[existingNodes[a].getAttribute("name")] = true;
} else {
existingMatches[existingNodes[a].getAttribute("match")] = true;
}
}
var pn = _.node.parentNode;
for(var y=0;y<imports.length;y++) {
if(!existingNames[imports[y].getAttribute("name")] && !existingMatches[imports[y].getAttribute("match")]) {
var clonednode = _.xObj.ownerDocument.importNode(imports[y],true);
//pn.insertBefore(clonednode,_.xObj);
pn.insertBefore(clonednode,childNodes(_.xObj,"template")[0]);
}
}
pn.removeChild(_.node);
} catch(ex) {
}
}
});
}
return xObj;
};
Teraz używając wcześniej wklejonego indeksu testu.html użyj tego dla transform.xsl
:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:include href="include.xsl" />
<xsl:output method="html"/>
<xsl:template match="/">
<xsl:call-template name="giveMeAnIncludedHeader" />
</xsl:template>
</xsl:stylesheet>
I to dla include.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="giveMeAnIncludedHeader">
<h1>Test</h1>
</xsl:template>
</xsl:stylesheet>
Z wcześniej opublikowaną poprawką w {[8] } to teraz wstawi dołączoną <h1>Test</h1>
we wszystkich przeglądarkach.
Możesz zobaczyć go w akcji tutaj: http://www.mpdreamz.nl/xsltest
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-20 21:21:31
To nie jest odpowiedź na pierwotne pytanie, ale podczas moich poszukiwań w Internecie szukając przykładowej transformacji xslt, która działa na chrome znalazłem linki do tego wątku wiele razy. Szukałem rozwiązania, które nie używa żadnych open-source lub innych bibliotek / wtyczek i działa dobrze z silverlight.
Problemem chrome i safari jest ograniczenie uniemożliwiające bezpośrednie ładowanie plików xml. Sugerowane obejście w http://www.mindlence.com/WP/?p=308 {[6] } jest załadowanie pliku xml dowolną inną metodą i przekazanie go jako ciąg znaków procesorowi xslt.
Dzięki takiemu podejściu udało mi się wykonać transformacje xsl w javascript i przekazać wynik do aplikacji silverlight poprzez HTML Bridge.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-23 03:54:44