QUrl AccelTree::baseUri(const QXmlNodeModelIndex &ni) const { switch(kind(toPreNumber(ni))) { case QXmlNodeModelIndex::Document: return baseUri(); case QXmlNodeModelIndex::Element: { const QXmlNodeModelIndex::Iterator::Ptr it(iterate(ni, QXmlNodeModelIndex::AxisAttribute)); QXmlNodeModelIndex next(it->next()); while(!next.isNull()) { if(next.name() == QXmlName(StandardNamespaces::xml, StandardLocalNames::base)) { const QUrl candidate(next.stringValue()); // TODO. The xml:base spec says to do URI escaping here. if(!candidate.isValid()) return QUrl(); else if(candidate.isRelative()) { const QXmlNodeModelIndex par(parent(ni)); if(par.isNull()) return baseUri().resolved(candidate); else return par.baseUri().resolved(candidate); } else return candidate; } next = it->next(); } /* We have no xml:base-attribute. Can any parent supply us a base URI? */ const QXmlNodeModelIndex par(parent(ni)); if(par.isNull()) return baseUri(); else return par.baseUri(); } case QXmlNodeModelIndex::ProcessingInstruction: /* Fallthrough. */ case QXmlNodeModelIndex::Comment: /* Fallthrough. */ case QXmlNodeModelIndex::Attribute: /* Fallthrough. */ case QXmlNodeModelIndex::Text: { const QXmlNodeModelIndex par(ni.iterate(QXmlNodeModelIndex::AxisParent)->next()); if(par.isNull()) return QUrl(); else return par.baseUri(); } case QXmlNodeModelIndex::Namespace: return QUrl(); } Q_ASSERT_X(false, Q_FUNC_INFO, "This line is never supposed to be reached."); return QUrl(); }
void AccelTree::copyNodeTo(const QXmlNodeModelIndex &node, QAbstractXmlReceiver *const receiver, const NodeCopySettings &settings) const { /* This code piece can be seen as a customized version of * QAbstractXmlReceiver::item/sendAsNode(). */ Q_ASSERT(receiver); Q_ASSERT(!node.isNull()); typedef QHash<QXmlName::PrefixCode, QXmlName::NamespaceCode> Binding; QStack<Binding> outputted; switch(node.kind()) { case QXmlNodeModelIndex::Element: { outputted.push(Binding()); /* Add the namespace for our element name. */ const QXmlName elementName(node.name()); receiver->startElement(elementName); if(!settings.testFlag(InheritNamespaces)) receiver->namespaceBinding(QXmlName(StandardNamespaces::StopNamespaceInheritance, 0, StandardPrefixes::StopNamespaceInheritance)); if(settings.testFlag(PreserveNamespaces)) node.sendNamespaces(receiver); else { /* Find the namespaces that we actually use and add them to outputted. These are drawn * from the element name, and the node's attributes. */ outputted.top().insert(elementName.prefix(), elementName.namespaceURI()); const QXmlNodeModelIndex::Iterator::Ptr attributes(iterate(node, QXmlNodeModelIndex::AxisAttribute)); QXmlNodeModelIndex attr(attributes->next()); while(!attr.isNull()) { const QXmlName &attrName = attr.name(); outputted.top().insert(attrName.prefix(), attrName.namespaceURI()); attr = attributes->next(); } Binding::const_iterator it(outputted.top().constBegin()); const Binding::const_iterator end(outputted.top().constEnd()); for(; it != end; ++it) receiver->namespaceBinding(QXmlName(it.value(), 0, it.key())); } /* Send the attributes of the element. */ { QXmlNodeModelIndex::Iterator::Ptr attributes(node.iterate(QXmlNodeModelIndex::AxisAttribute)); QXmlNodeModelIndex attribute(attributes->next()); while(!attribute.isNull()) { const QString &v = attribute.stringValue(); receiver->attribute(attribute.name(), QStringRef(&v)); attribute = attributes->next(); } } /* Send the children of the element. */ copyChildren(node, receiver, settings); receiver->endElement(); outputted.pop(); break; } case QXmlNodeModelIndex::Document: { /* We need to intercept and grab the elements of the document node, such * that we preserve/inherit preference applies to them. */ receiver->startDocument(); copyChildren(node, receiver, settings); receiver->endDocument(); break; } default: receiver->item(node); } }