void XSchemaSequence::scanForElements(QDomElement &element, void * /*context*/) { QString name = element.localName(); if(element.prefix() == _root->namespacePrefix()) { if(name == IO_XSD_ANNOTATION) { readHandleAnnotation(element); return; } else if(name == IO_XSD_TAGELEMENT) { readHandleObject(element, new XSchemaElement(this, _root)); return ; } else if(name == IO_XSD_GROUP) { readHandleObject(element, new XSchemaGroup(this, _root)); return ; } else if(name == IO_XSD_CHOICE) { readHandleObject(element, new XSchemaChoice(this, _root)); return ; } else if(name == IO_XSD_SEQUENCE) { readHandleObject(element, new XSchemaSequence(this, _root)); return ; } else if(name == IO_XSD_ANY) { readHandleObject(element, new XSchemaAny(this, _root)); return ; } } raiseError(this, element, true); }
// stripExtraNS // // This function removes namespace information from various nodes for // display purposes only (the element is pretty much useless for processing // after this). We do this because QXml is a bit overzealous about outputting // redundant namespaces. static QDomElement stripExtraNS(const QDomElement &e) { // find closest parent with a namespace QDomNode par = e.parentNode(); while(!par.isNull() && par.namespaceURI().isNull()) par = par.parentNode(); bool noShowNS = false; if(!par.isNull() && par.namespaceURI() == e.namespaceURI()) noShowNS = true; // build qName (prefix:localName) QString qName; if(!e.prefix().isEmpty()) qName = e.prefix() + ':' + e.localName(); else qName = e.tagName(); QDomElement i; int x; if(noShowNS) i = e.ownerDocument().createElement(qName); else i = e.ownerDocument().createElementNS(e.namespaceURI(), qName); // copy attributes QDomNamedNodeMap al = e.attributes(); for(x = 0; x < al.count(); ++x) { QDomAttr a = al.item(x).cloneNode().toAttr(); // don't show xml namespace if(a.namespaceURI() == NS_XML) i.setAttribute(QString("xml:") + a.name(), a.value()); else i.setAttributeNodeNS(a); } // copy children QDomNodeList nl = e.childNodes(); for(x = 0; x < nl.count(); ++x) { QDomNode n = nl.item(x); if(n.isElement()) i.appendChild(stripExtraNS(n.toElement())); else i.appendChild(n.cloneNode()); } return i; }
void XSchemaSimpleTypeUnion::scanForElements(QDomElement &element, void * /*context*/) { QString name = element.localName(); if(element.prefix() == _root->namespacePrefix()) { if(name == IO_XSD_ANNOTATION) { readHandleAnnotation(element); } else if(name == IO_XSD_SIMPLETYPE) { readHandleObject(element, new XSchemaElement(this, _root)); } else { raiseError(this, element, true); } } else { raiseError(this, element, true); } }
QString XmlProtocol::elementToString(const QDomElement &e, bool clip) { if(elem.isNull()) elem = elemDoc.importNode(docElement(), true).toElement(); // Determine the appropriate 'fakeNS' to use QString ns; // first, check root namespace QString pre = e.prefix(); if(pre.isNull()) pre = ""; if(pre == elem.prefix()) { ns = elem.namespaceURI(); } else { // scan the root attributes for 'xmlns' (oh joyous hacks) QDomNamedNodeMap al = elem.attributes(); int n; for(n = 0; n < al.count(); ++n) { QDomAttr a = al.item(n).toAttr(); QString s = a.name(); int x = s.indexOf(':'); if(x != -1) s = s.mid(x+1); else s = ""; if(pre == s) { ns = a.value(); break; } } if(n >= al.count()) { // if we get here, then no appropriate ns was found. use root then.. ns = elem.namespaceURI(); } } // build qName QString qn; if(!elem.prefix().isEmpty()) qn = elem.prefix() + ':'; qn += elem.localName(); // make the string return sanitizeForStream(xmlToString(e, ns, qn, clip)); }
void XSchemaSimpleTypeRestriction::scanForElements(QDomElement &element, void *context) { XScanContext *theContext = (XScanContext*) context; QString name = element.localName(); QString value = element.attribute(IO_FACET_ATTR_VALUE, ""); if(element.prefix() == _root->namespacePrefix()) { if(name == IO_XSD_ANNOTATION) { readHandleAnnotation(element); } else if(name == IO_XSD_SIMPLETYPE) { if(theContext->childFound) { raiseError(this, element, true); } theContext->childFound = true; readHandleObject(element, new XSchemaElement(this, _root)); /*} else if( scanForFacets( name, value, _facets ) ) { TODO: fare poi // nothing TODO: delete*/ } else if(name == IO_XSD_MINEXCLUSIVE) { _facets._minExclusive = value; } else if(name == IO_XSD_MININCLUSIVE) { _facets._minInclusive = value; } else if(name == IO_XSD_MAXEXCLUSIVE) { _facets._maxExclusive = value; } else if(name == IO_XSD_MAXINCLUSIVE) { _facets._maxInclusive = value; } else if(name == IO_XSD_TOTALDIGITS) { _facets._totalDigits = value; } else if(name == IO_XSD_FRACTIONDIGITS) { _facets._fractionDigits = value; } else if(name == IO_XSD_LENGTH) { _facets._length = value; } else if(name == IO_XSD_MINLENGTH) { _facets._minLength = value; } else if(name == IO_XSD_MAXLENGTH) { _facets._maxLength = value; } else if(name == IO_XSD_ENUMERATION) { // TODO: WRONG!!!! _facets._enumeration.append(value); } else if(name == IO_XSD_WHITESPACE) { // TODO: WRONG!!!! _facets._whiteSpace = value; } else if(name == IO_XSD_PATTERN) { _facets._pattern = value; } else { raiseError(this, element, true); } } else { raiseError(this, element, true); } }
void cleanDomElement(QDomElement &pDomElement, QMap<QString, QString> &pElementsAttributes) { // Serialise all the element's attributes and sort their serialised version // before removing them from the element and adding a new attribute that // will later on be used for string replacement static qulonglong attributeNumber = 0; static const int ULLONG_WIDTH = ceil(log(ULLONG_MAX)); if (pDomElement.hasAttributes()) { QStringList serialisedAttributes = QStringList(); QDomNamedNodeMap domElementAttributes = pDomElement.attributes(); QDomAttr attributeNode; while (domElementAttributes.count()) { // Serialise (ourselves) the element's attribute // Note: to rely on QDomNode::save() to do the serialisation isn't // good enough. Indeed, if it is going to be fine for an // attribute that doesn't have a prefix, e.g. // name="my_name" // it may not be fine for an attribute with a prefix, e.g. // cmeta:id="my_cmeta_id" // since depending on how that attribute has been created // (i.e. using QDomDocument::createAttribute() or // QDomDocument::createAttributeNS()), then it may or not have // a namespace associated with it. If it does, then its // serialisation will look something like // cmeta:id="my_cmeta_id" xmlns:cmeta="http://www.cellml.org/metadata/1.0#" // which is clearly not what we want since that's effectively // two attributes in one. So, we need to separate them, which // is what we do here, after making sure that the namespace // for the attribute is not already defined for the given DOM // element... attributeNode = domElementAttributes.item(0).toAttr(); if (attributeNode.namespaceURI().isEmpty()) { serialisedAttributes << attributeNode.name()+"=\""+attributeNode.value()+"\""; } else { serialisedAttributes << attributeNode.prefix()+":"+attributeNode.name()+"=\""+attributeNode.value()+"\""; if ( attributeNode.prefix().compare(pDomElement.prefix()) && attributeNode.namespaceURI().compare(pDomElement.namespaceURI())) { serialisedAttributes << "xmlns:"+attributeNode.prefix()+"=\""+attributeNode.namespaceURI()+"\""; } } // Remove the attribute node from the element pDomElement.removeAttributeNode(attributeNode); } // Sort the serialised attributes, using the attributes' name, and // remove duplicates, if any std::sort(serialisedAttributes.begin(), serialisedAttributes.end(), sortSerialisedAttributes); serialisedAttributes.removeDuplicates(); // Keep track of the serialisation of the element's attribute QString elementAttributes = QString("Element%1Attributes").arg(++attributeNumber, ULLONG_WIDTH, 10, QChar('0')); pElementsAttributes.insert(elementAttributes, serialisedAttributes.join(" ")); // Add a new attribute to the element // Note: this attribute, once serialised by QDomDocument::save(), will // be used to do a string replacement (see // qDomDocumentToString())... domElementAttributes.setNamedItem(pDomElement.ownerDocument().createAttribute(elementAttributes)); } // Recursively clean ourselves for (QDomElement childElement = pDomElement.firstChildElement(); !childElement.isNull(); childElement = childElement.nextSiblingElement()) { cleanDomElement(childElement, pElementsAttributes); } }
bool Reader::loadLayers(ZipReader &zip, const QDomElement& stack, QPoint offset) { // TODO are layer coordinates relative to stack coordinates? // The spec, as of this writing, is not clear on this. offset += QPoint( stack.attribute("x", "0").toInt(), stack.attribute("y", "0").toInt() ); QDomNodeList nodes = stack.childNodes(); // Iterate backwards to get the layers in the right order (layers are always added to the top of the stack) for(int n=nodes.count()-1;n>=0;--n) { QDomElement e = nodes.at(n).toElement(); if(e.isNull()) continue; if(e.tagName()=="layer") { // Check for unknown attributes const char *layerattrs[] = { "x", "y", "name", "src", "opacity", "visibility", "composite-op", 0 }; if(!isKnown(e.attributes(), layerattrs)) _warnings |= ORA_EXTENDED; // Load content image from the file const QString src = e.attribute("src"); QImage content; { QByteArray image = zip.fileData(src); if(image.isNull()) { _error = QApplication::tr("Couldn't get layer %1").arg(src); return false; } if(content.loadFromData(image, "png")==false) { _error = QApplication::tr("Couldn't load layer %1").arg(src); return false; } } // Create layer QString name = e.attribute("name", QApplication::tr("Unnamed layer")); _commands.append(MessagePtr(new protocol::LayerCreate( 1, ++_layerid, 0, name ))); QPoint layerPos = offset + QPoint( e.attribute("x", "0").toInt(), e.attribute("y", "0").toInt() ); _commands.append(net::putQImage(_layerid, layerPos.x(), layerPos.y(), content, false)); QString compositeOp = e.attribute("composite-op", "src-over"); int blendmode = dpcore::blendModeSvg(compositeOp); if(blendmode<0) { _warnings |= ORA_EXTENDED; blendmode = 1; } _commands.append(MessagePtr(new protocol::LayerAttributes( _layerid, qRound(255 * e.attribute("opacity", "1.0").toDouble()), blendmode ))); // TODO visibility flag //layer->setHidden(e.attribute("visibility", "visible") != "visible"); } else if(e.tagName()=="stack") { // Nested stacks are not fully supported _warnings |= ORA_NESTED; if(loadLayers(zip, e, offset)==false) return false; } else if(e.namespaceURI()==DP_NAMESPACE && e.localName()=="annotations") { loadAnnotations(e); } else if(e.namespaceURI()==DP_NAMESPACE) { qWarning() << "Unhandled drawpile extension in stack:" << e.tagName(); _warnings |= ORA_EXTENDED; } else if(e.prefix()=="") { qWarning() << "Unhandled stack element:" << e.tagName(); _warnings |= ORA_EXTENDED; } } return true; }