domwriterimpl.cpp
来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,852 行 · 第 1/5 页
CPP
1,852 行
} else { tmpEncoding = docu->getActualEncoding(); if ( tmpEncoding && *tmpEncoding) { fEncodingUsed = tmpEncoding; } } } } /** * The end-of-line sequence of characters to be used in the XML being * written out. The only permitted values are these: * . null * * Use a default end-of-line sequence. DOM implementations should choose * the default to match the usual convention for text files in the * environment being used. Implementations must choose a default * sequence that matches one of those allowed by 2.11 "End-of-Line * Handling". * * CR The carriage-return character (#xD) * CR-LF The carriage-return and line-feed characters (#xD #xA) * LF The line-feed character (#xA) * * The default value for this attribute is null */ fNewLineUsed = (fNewLine && *fNewLine)? fNewLine : gEOLSeq; /** * get Document Version */ const DOMDocument *docu = (nodeToWrite->getNodeType() == DOMNode::DOCUMENT_NODE)? (const DOMDocument*)nodeToWrite : nodeToWrite->getOwnerDocument(); if (docu) { fDocumentVersion = docu->getVersion(); } fErrorCount = 0;}//// Characters not representable in output encoding,//// 1. CHARACTER DATA (outside of markup) --- no error// ordinary character -> numeric character reference// '<' and '&' -> < and &//// 2. Within MARKUP, but outside of attributes// reported as an error --- ERROR// markup:// start tag done// end tag done// empty element tag done// entity references done// character references // REVISIT// comments done// CDATA section delimiters done, done// document type declarartions done// processing instructions (PI) done//// 3. With in ATTRIBUTE// -> numeric character reference// no quotes -> in quotes// with quotes, no apostrophe -> in apostrophe// with quotes and apostrophe -> in quotes and "//// 4. CDATA sections// "split_cdata_section" true --- char ref// false --- ERROR//// ---------------------------------------------------------------------------// Stream out a DOM node, and, recursively, all of its children. This// function is the heart of writing a DOM tree out as XML source. Give it// a document node and it will do the whole thing.// ---------------------------------------------------------------------------void DOMWriterImpl::processNode(const DOMNode* const nodeToWrite, int level){ // Get the name and value out for convenience const XMLCh* nodeName = nodeToWrite->getNodeName(); const XMLCh* nodeValue = nodeToWrite->getNodeValue(); unsigned long lent = XMLString::stringLen(nodeValue); switch (nodeToWrite->getNodeType()) { case DOMNode::TEXT_NODE: { if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT) break; if (getFeature(FORMAT_PRETTY_PRINT_ID)) { lineFeedInTextNodePrinted = false; lastWhiteSpaceInTextNode = 0; if(XMLString::isAllWhiteSpace(nodeValue)) { // skips whitespace-only text nodes unless whitespace-in-element is set. if (!getFeature(WHITESPACE_IN_ELEMENT_CONTENT_ID)) { break; } else { // // we need to trace if newline(s) have been printed out // to avoid generate extra newline for pretty printing, // as well as the number of whitespaces after the last // newline character to do indentation properly. // int pos = XMLString::lastIndexOf(nodeValue, chLF); if (-1 != pos) { lineFeedInTextNodePrinted = true; lastWhiteSpaceInTextNode = lent - pos; } else { // for those platforms using chCR alone as // a newline character pos = XMLString::lastIndexOf(nodeValue, chCR); if (-1 != pos) { lineFeedInTextNodePrinted = true; lastWhiteSpaceInTextNode = lent - pos; } } } } } setURCharRef(); // character data fFormatter->formatBuf(nodeValue, lent, XMLFormatter::CharEscapes); break; } case DOMNode::PROCESSING_INSTRUCTION_NODE: { if (checkFilter(nodeToWrite) != DOMNodeFilter::FILTER_ACCEPT) break; if(level == 1) printNewLine(); printNewLine(); printIndent(level); TRY_CATCH_THROW ( *fFormatter << XMLFormatter::NoEscapes << gStartPI << nodeName; if (lent > 0) { *fFormatter << chSpace << nodeValue; } *fFormatter << gEndPI; ,true ) break; } case DOMNode::DOCUMENT_NODE: // Not to be shown to Filter { // output BOM if needed processBOM(); setURCharRef(); const DOMDocument *docu = (const DOMDocument*)nodeToWrite; //[23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' //[24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') //[80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName //[32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) // if (getFeature(XML_DECLARATION)) { const XMLCh* versionNo = (docu->getVersion()) ? docu->getVersion() : gXMLDecl_ver10; *fFormatter << gXMLDecl_VersionInfo << versionNo << gXMLDecl_separator; // use the encoding resolved in initSession() *fFormatter << gXMLDecl_EncodingDecl << fEncodingUsed << gXMLDecl_separator; const XMLCh* st = (docu->getStandalone())? XMLUni::fgYesString : XMLUni::fgNoString; *fFormatter << gXMLDecl_SDDecl << st << gXMLDecl_separator; *fFormatter << gXMLDecl_endtag; } DOMNodeSPtr child = nodeToWrite->getFirstChild(); while( child != 0) { processNode(child, level); child = child->getNextSibling(); } printNewLine(); break; } case DOMNode::DOCUMENT_FRAGMENT_NODE: { setURCharRef(); DOMNode *child = nodeToWrite->getFirstChild(); while( child != 0) { processNode(child, level); child = child->getNextSibling(); } printNewLine(); break; } case DOMNode::ELEMENT_NODE: { DOMNodeFilter::FilterAction filterAction = checkFilter(nodeToWrite); if ( filterAction == DOMNodeFilter::FILTER_REJECT) break; if (!lineFeedInTextNodePrinted) { if(level == 1) printNewLine(); printNewLine(); } else { lineFeedInTextNodePrinted = false; } printIndent(level); //track the line number the current node begins on int nodeLine = fCurrentLine; // add an entry in the namespace stack RefHashTableOf<XMLCh>* namespaceMap=NULL; if ( filterAction == DOMNodeFilter::FILTER_ACCEPT) { // this element attributes child elements // accept yes yes yes // skip no no yes // TRY_CATCH_THROW ( // The name has to be representable without any escapes *fFormatter << XMLFormatter::NoEscapes << chOpenAngle << nodeName; ,true ) // Output any attributes on this element setURCharRef(); DOMNamedNodeMap *attributes = nodeToWrite->getAttributes(); int attrCount = attributes->getLength(); // check if the namespace for the current node is already defined const XMLCh* prefix = nodeToWrite->getPrefix(); const XMLCh* uri = nodeToWrite->getNamespaceURI(); if(uri && uri[0]) { if(prefix==0 || prefix[0]==0) prefix=XMLUni::fgZeroLenString; bool bPrefixDeclared=false; for(int i=fNamespaceStack->size()-1;i>=0;i--) { RefHashTableOf<XMLCh>* curNamespaceMap=fNamespaceStack->elementAt(i); const XMLCh* thisUri=curNamespaceMap->get((void*)prefix); if(thisUri && XMLString::equals(thisUri,nodeToWrite->getNamespaceURI())) { bPrefixDeclared=true; break; } } if(!bPrefixDeclared) { if(namespaceMap==NULL) { namespaceMap=new (fMemoryManager) RefHashTableOf<XMLCh>(12, false, fMemoryManager); fNamespaceStack->addElement(namespaceMap); } namespaceMap->put((void*)prefix,(XMLCh*)nodeToWrite->getNamespaceURI()); *fFormatter << XMLFormatter::NoEscapes << chSpace << XMLUni::fgXMLNSString; if(!XMLString::equals(prefix,XMLUni::fgZeroLenString)) *fFormatter << chColon << prefix; *fFormatter << chEqual << chDoubleQuote << XMLFormatter::AttrEscapes << nodeToWrite->getNamespaceURI() << XMLFormatter::NoEscapes << chDoubleQuote; } } bool discard = getFeature(DISCARD_DEFAULT_CONTENT_ID); for (int i = 0; i < attrCount; i++) { DOMAttrSPtr attribute = (DOMAttr*)attributes->item(i); // Not to be shown to Filter // //"discard-default-content" // true // [required] (default) // Use whatever information available to the implementation // (i.e. XML schema, DTD, the specified flag on Attr nodes, // and so on) to decide what attributes and content should be // discarded or not. // Note that the specified flag on Attr nodes in itself is // not always reliable, it is only reliable when it is set // to false since the only case where it can be set to false // is if the attribute was created by the implementation. // The default content won't be removed if an implementation // does not have any information available. // false // [required] // Keep all attributes and all content. // if (discard && !((DOMAttr*)attribute )->getSpecified()) continue; // // Again the name has to be completely representable. But the // attribute can have refs and requires the attribute style // escaping. // // if this attribute is a namespace declaration, add it to the namespace map for the current level const XMLCh* ns = attribute->getNamespaceURI(); if (ns != 0 ) { if(XMLString::equals(ns, XMLUni::fgXMLNSURIName)) { if(namespaceMap==NULL) { namespaceMap=new (fMemoryManager) RefHashTableOf<XMLCh>(12, false, fMemoryManager); fNamespaceStack->addElement(namespaceMap); } const XMLCh* nsPrefix = attribute->getLocalName(); if(XMLString::equals(attribute->getNodeName(),XMLUni::fgXMLNSString)) nsPrefix = XMLUni::fgZeroLenString; if(namespaceMap->containsKey((void*)nsPrefix)) continue; namespaceMap->put((void*)attribute->getLocalName(),(XMLCh*)attribute->getNodeValue()); } else if(!XMLString::equals(ns, XMLUni::fgXMLURIName)) { // check if the namespace for the current node is already defined const XMLCh* prefix = attribute->getPrefix(); if(prefix && prefix[0]) { bool bPrefixDeclared=false; for(int i=fNamespaceStack->size()-1;i>=0;i--) { RefHashTableOf<XMLCh>* curNamespaceMap=fNamespaceStack->elementAt(i); const XMLCh* thisUri=curNamespaceMap->get((void*)prefix); if(thisUri && XMLString::equals(thisUri,attribute->getNamespaceURI())) { bPrefixDeclared=true; break; } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?