15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This file is part of the XSL implementation. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2008, 2012 Apple Inc. All rights reserved. 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/xml/XSLStyleSheet.h" 2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h" 2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Node.h" 2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/TransformSource.h" 2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Frame.h" 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Page.h" 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/xml/XSLImportRule.h" 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/xml/XSLTProcessor.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/xml/parser/XMLDocumentParserScope.h" 33591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/xml/parser/XMLParserInput.h" 34591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/text/CString.h" 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <libxml/uri.h> 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <libxslt/xsltutils.h> 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)XSLStyleSheet::XSLStyleSheet(XSLImportRule* parentRule, const String& originalURL, const KURL& finalURL) 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_ownerNode(0) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_originalURL(originalURL) 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_finalURL(finalURL) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_isDisabled(false) 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_embedded(false) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_processed(false) // Child sheets get marked as processed when the libxslt engine has finally seen them. 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_stylesheetDoc(0) 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_stylesheetDocTaken(false) 50faba41ffa661cd78b7a334ae61a88fa41952497cTorne (Richard Coles) , m_compilationFailed(false) 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_parentStyleSheet(parentRule ? parentRule->parentStyleSheet() : 0) 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL, bool embedded) 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_ownerNode(parentNode) 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_originalURL(originalURL) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_finalURL(finalURL) 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_isDisabled(false) 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_embedded(embedded) 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_processed(true) // The root sheet starts off processed. 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_stylesheetDoc(0) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_stylesheetDocTaken(false) 64faba41ffa661cd78b7a334ae61a88fa41952497cTorne (Richard Coles) , m_compilationFailed(false) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_parentStyleSheet(0) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)XSLStyleSheet::~XSLStyleSheet() 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_stylesheetDocTaken) 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlFreeDoc(m_stylesheetDoc); 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < m_children.size(); ++i) { 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_children.at(i)->parentStyleSheet() == this); 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_children.at(i)->setParentStyleSheet(0); 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool XSLStyleSheet::isLoading() const 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < m_children.size(); ++i) { 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_children.at(i)->isLoading()) 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void XSLStyleSheet::checkLoaded() 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isLoading()) 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (XSLStyleSheet* styleSheet = parentStyleSheet()) 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) styleSheet->checkLoaded(); 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (ownerNode()) 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ownerNode()->sheetLoaded(); 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)xmlDocPtr XSLStyleSheet::document() 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_embedded && ownerDocument() && ownerDocument()->transformSource()) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return (xmlDocPtr)ownerDocument()->transformSource()->platformSource(); 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_stylesheetDoc; 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void XSLStyleSheet::clearDocuments() 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_stylesheetDoc = 0; 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < m_children.size(); ++i) { 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) XSLImportRule* import = m_children.at(i).get(); 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (import->styleSheet()) 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) import->styleSheet()->clearDocuments(); 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1163464d02a173573db42f8ee6bb07bb74fabf4f5f2Ben MurdochResourceFetcher* XSLStyleSheet::fetcher() 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Document* document = ownerDocument(); 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!document) 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 1213464d02a173573db42f8ee6bb07bb74fabf4f5f2Ben Murdoch return document->fetcher(); 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 124591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochbool XSLStyleSheet::parseString(const String& source) 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Parse in a single chunk into an xmlDocPtr 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!m_stylesheetDocTaken) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlFreeDoc(m_stylesheetDoc); 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_stylesheetDocTaken = false; 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) PageConsole* console = 0; 132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) Frame* frame = ownerDocument()->frame(); 133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (frame && frame->page()) 134926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) console = frame->page()->console(); 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1363464d02a173573db42f8ee6bb07bb74fabf4f5f2Ben Murdoch XMLDocumentParserScope scope(fetcher(), XSLTProcessor::genericErrorFunc, XSLTProcessor::parseErrorFunc, console); 137591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch XMLParserInput input(source); 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 139591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(input.data(), input.size()); 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!ctxt) 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_parentStyleSheet) { 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The XSL transform may leave the newly-transformed document 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // with references to the symbol dictionaries of the style sheet 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // and any of its children. XML document disposal can corrupt memory 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // if a document uses more than one symbol dictionary, so we 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // ensure that all child stylesheets use the same dictionaries as their 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // parents. 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlDictFree(ctxt->dict); 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ctxt->dict = m_parentStyleSheet->m_stylesheetDoc->dict; 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlDictReference(ctxt->dict); 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 155591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch m_stylesheetDoc = xmlCtxtReadMemory(ctxt, input.data(), input.size(), 156591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch finalURL().string().utf8().data(), input.encoding(), 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA); 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 159591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch xmlFreeParserCtxt(ctxt); 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) loadChildSheets(); 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_stylesheetDoc; 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void XSLStyleSheet::loadChildSheets() 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!document()) 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlNodePtr stylesheetRoot = document()->children; 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Top level children may include other things such as DTD nodes, we ignore those. 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (stylesheetRoot && stylesheetRoot->type != XML_ELEMENT_NODE) 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stylesheetRoot = stylesheetRoot->next; 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_embedded) { 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We have to locate (by ID) the appropriate embedded stylesheet element, so that we can walk the 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // import/include list. 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlAttrPtr idNode = xmlGetID(document(), (const xmlChar*)(finalURL().string().utf8().data())); 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!idNode) 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stylesheetRoot = idNode->parent; 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: Need to handle an external URI with a # in it. This is a pretty minor edge case, so we'll deal 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // with it later. 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (stylesheetRoot) { 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Walk the children of the root element and look for import/include elements. 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Imports must occur first. 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlNodePtr curr = stylesheetRoot->children; 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (curr) { 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (curr->type != XML_ELEMENT_NODE) { 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) curr = curr->next; 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (IS_XSLT_ELEM(curr) && IS_XSLT_NAME(curr, "import")) { 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlChar* uriRef = xsltGetNsProp(curr, (const xmlChar*)"href", XSLT_NAMESPACE); 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) loadChildSheet(String::fromUTF8((const char*)uriRef)); 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlFree(uriRef); 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) curr = curr->next; 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Now handle includes. 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (curr) { 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (curr->type == XML_ELEMENT_NODE && IS_XSLT_ELEM(curr) && IS_XSLT_NAME(curr, "include")) { 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlChar* uriRef = xsltGetNsProp(curr, (const xmlChar*)"href", XSLT_NAMESPACE); 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) loadChildSheet(String::fromUTF8((const char*)uriRef)); 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlFree(uriRef); 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) curr = curr->next; 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void XSLStyleSheet::loadChildSheet(const String& href) 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) OwnPtr<XSLImportRule> childRule = XSLImportRule::create(this, href); 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) XSLImportRule* c = childRule.get(); 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_children.append(childRule.release()); 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) c->loadSheet(); 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)xsltStylesheetPtr XSLStyleSheet::compileStyleSheet() 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: Hook up error reporting for the stylesheet compilation process. 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_embedded) 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return xsltLoadStylesheetPI(document()); 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 231faba41ffa661cd78b7a334ae61a88fa41952497cTorne (Richard Coles) // Certain libxslt versions are corrupting the xmlDoc on compilation failures - 232faba41ffa661cd78b7a334ae61a88fa41952497cTorne (Richard Coles) // hence attempting to recompile after a failure is unsafe. 233faba41ffa661cd78b7a334ae61a88fa41952497cTorne (Richard Coles) if (m_compilationFailed) 234faba41ffa661cd78b7a334ae61a88fa41952497cTorne (Richard Coles) return 0; 235faba41ffa661cd78b7a334ae61a88fa41952497cTorne (Richard Coles) 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // xsltParseStylesheetDoc makes the document part of the stylesheet 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // so we have to release our pointer to it. 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_stylesheetDocTaken); 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xsltStylesheetPtr result = xsltParseStylesheetDoc(m_stylesheetDoc); 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result) 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_stylesheetDocTaken = true; 242faba41ffa661cd78b7a334ae61a88fa41952497cTorne (Richard Coles) else 243faba41ffa661cd78b7a334ae61a88fa41952497cTorne (Richard Coles) m_compilationFailed = true; 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return result; 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void XSLStyleSheet::setParentStyleSheet(XSLStyleSheet* parent) 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_parentStyleSheet = parent; 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Document* XSLStyleSheet::ownerDocument() 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (XSLStyleSheet* styleSheet = this; styleSheet; styleSheet = styleSheet->parentStyleSheet()) { 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* node = styleSheet->ownerNode(); 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (node) 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return node->document(); 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)xmlDocPtr XSLStyleSheet::locateStylesheetSubResource(xmlDocPtr parentDoc, const xmlChar* uri) 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool matchedParent = (parentDoc == document()); 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < m_children.size(); ++i) { 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) XSLImportRule* import = m_children.at(i).get(); 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) XSLStyleSheet* child = import->styleSheet(); 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!child) 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (matchedParent) { 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (child->processed()) 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; // libxslt has been given this sheet already. 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Check the URI of the child stylesheet against the doc URI. 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // In order to ensure that libxml canonicalized both URLs, we get the original href 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // string from the import rule and canonicalize it using libxml before comparing it 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // with the URI argument. 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CString importHref = import->href().utf8(); 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlChar* base = xmlNodeGetBase(parentDoc, (xmlNodePtr)parentDoc); 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlChar* childURI = xmlBuildURI((const xmlChar*)importHref.data(), base); 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool equalURIs = xmlStrEqual(uri, childURI); 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlFree(base); 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlFree(childURI); 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (equalURIs) { 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) child->markAsProcessed(); 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return child->document(); 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) xmlDocPtr result = import->styleSheet()->locateStylesheetSubResource(parentDoc, uri); 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result) 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return result; 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void XSLStyleSheet::markAsProcessed() 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_processed); 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_stylesheetDocTaken); 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_processed = true; 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_stylesheetDocTaken = true; 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore 307