Пример #1
0
Node* DOMPatchSupport::patchNode(Node* node, const String& markup, ExceptionState& exceptionState)
{
    // Don't parse <html> as a fragment.
    if (node->isDocumentNode() || (node->parentNode() && node->parentNode()->isDocumentNode())) {
        patchDocument(markup);
        return 0;
    }

    Node* previousSibling = node->previousSibling();
    RefPtrWillBeRawPtr<DocumentFragment> fragment = DocumentFragment::create(m_document);
    Node* targetNode = node->parentElementOrShadowRoot() ? node->parentElementOrShadowRoot() : m_document.documentElement();

    // Use the document BODY as the context element when editing immediate shadow root children,
    // as it provides an equivalent parsing context.
    if (targetNode->isShadowRoot())
        targetNode = m_document.body();
    Element* targetElement = toElement(targetNode);

    // FIXME: This code should use one of createFragment* in markup.h
    if (m_document.isHTMLDocument())
        fragment->parseHTML(markup, targetElement);
    else
        fragment->parseXML(markup, targetElement);

    // Compose the old list.
    ContainerNode* parentNode = node->parentNode();
    Vector<OwnPtr<Digest> > oldList;
    for (Node* child = parentNode->firstChild(); child; child = child->nextSibling())
        oldList.append(createDigest(child, 0));

    // Compose the new list.
    String markupCopy = markup.lower();
    Vector<OwnPtr<Digest> > newList;
    for (Node* child = parentNode->firstChild(); child != node; child = child->nextSibling())
        newList.append(createDigest(child, 0));
    for (Node* child = fragment->firstChild(); child; child = child->nextSibling()) {
        if (isHTMLHeadElement(*child) && !child->firstChild() && markupCopy.find("</head>") == kNotFound)
            continue; // HTML5 parser inserts empty <head> tag whenever it parses <body>
        if (isHTMLBodyElement(*child) && !child->firstChild() && markupCopy.find("</body>") == kNotFound)
            continue; // HTML5 parser inserts empty <body> tag whenever it parses </head>
        newList.append(createDigest(child, &m_unusedNodesMap));
    }
    for (Node* child = node->nextSibling(); child; child = child->nextSibling())
        newList.append(createDigest(child, 0));

    if (!innerPatchChildren(parentNode, oldList, newList, exceptionState)) {
        // Fall back to total replace.
        if (!m_domEditor->replaceChild(parentNode, fragment.release(), node, exceptionState))
            return 0;
    }
    return previousSibling ? previousSibling->nextSibling() : parentNode->firstChild();
}
Пример #2
0
bool XMLFile::BeginLoad(Deserializer& source)
{
    unsigned dataSize = source.GetSize();
    if (!dataSize && !source.GetName().Empty())
    {
        URHO3D_LOGERROR("Zero sized XML data in " + source.GetName());
        return false;
    }

    SharedArrayPtr<char> buffer(new char[dataSize]);
    if (source.Read(buffer.Get(), dataSize) != dataSize)
        return false;

    if (!document_->load_buffer(buffer.Get(), dataSize))
    {
        URHO3D_LOGERROR("Could not parse XML data from " + source.GetName());
        document_->reset();
        return false;
    }

    XMLElement rootElem = GetRoot();
    String inherit = rootElem.GetAttribute("inherit");
    if (!inherit.Empty())
    {
        // The existence of this attribute indicates this is an RFC 5261 patch file
        ResourceCache* cache = GetSubsystem<ResourceCache>();
        // If being async loaded, GetResource() is not safe, so use GetTempResource() instead
        XMLFile* inheritedXMLFile = GetAsyncLoadState() == ASYNC_DONE ? cache->GetResource<XMLFile>(inherit) :
            cache->GetTempResource<XMLFile>(inherit);
        if (!inheritedXMLFile)
        {
            URHO3D_LOGERRORF("Could not find inherited XML file: %s", inherit.CString());
            return false;
        }

        // Patch this XMLFile and leave the original inherited XMLFile as it is
        UniquePtr<pugi::xml_document> patchDocument(document_.Detach());
        document_ = new pugi::xml_document();
        document_->reset(*inheritedXMLFile->document_);
        Patch(rootElem);

        // Store resource dependencies so we know when to reload/repatch when the inherited resource changes
        cache->StoreResourceDependency(this, inherit);

        // Approximate patched data size
        dataSize += inheritedXMLFile->GetMemoryUse();
    }

    // Note: this probably does not reflect internal data structure size accurately
    SetMemoryUse(dataSize);
    return true;
}