1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/nsXMLContentSerializer.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,371 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * nsIContentSerializer implementation that can be used with an 1.11 + * nsIDocumentEncoder to convert an XML DOM to an XML string that 1.12 + * could be parsed into more or less the original DOM. 1.13 + */ 1.14 + 1.15 +#ifndef nsXMLContentSerializer_h__ 1.16 +#define nsXMLContentSerializer_h__ 1.17 + 1.18 +#include "mozilla/Attributes.h" 1.19 +#include "nsIContentSerializer.h" 1.20 +#include "nsISupportsUtils.h" 1.21 +#include "nsCOMPtr.h" 1.22 +#include "nsTArray.h" 1.23 +#include "nsString.h" 1.24 + 1.25 +#define kIndentStr NS_LITERAL_STRING(" ") 1.26 +#define kEndTag NS_LITERAL_STRING("</") 1.27 + 1.28 +class nsIAtom; 1.29 +class nsIDOMNode; 1.30 +class nsINode; 1.31 + 1.32 +class nsXMLContentSerializer : public nsIContentSerializer { 1.33 + public: 1.34 + nsXMLContentSerializer(); 1.35 + virtual ~nsXMLContentSerializer(); 1.36 + 1.37 + NS_DECL_ISUPPORTS 1.38 + 1.39 + NS_IMETHOD Init(uint32_t flags, uint32_t aWrapColumn, 1.40 + const char* aCharSet, bool aIsCopying, 1.41 + bool aRewriteEncodingDeclaration) MOZ_OVERRIDE; 1.42 + 1.43 + NS_IMETHOD AppendText(nsIContent* aText, int32_t aStartOffset, 1.44 + int32_t aEndOffset, nsAString& aStr) MOZ_OVERRIDE; 1.45 + 1.46 + NS_IMETHOD AppendCDATASection(nsIContent* aCDATASection, 1.47 + int32_t aStartOffset, int32_t aEndOffset, 1.48 + nsAString& aStr) MOZ_OVERRIDE; 1.49 + 1.50 + NS_IMETHOD AppendProcessingInstruction(nsIContent* aPI, 1.51 + int32_t aStartOffset, 1.52 + int32_t aEndOffset, 1.53 + nsAString& aStr) MOZ_OVERRIDE; 1.54 + 1.55 + NS_IMETHOD AppendComment(nsIContent* aComment, int32_t aStartOffset, 1.56 + int32_t aEndOffset, nsAString& aStr) MOZ_OVERRIDE; 1.57 + 1.58 + NS_IMETHOD AppendDoctype(nsIContent *aDoctype, 1.59 + nsAString& aStr) MOZ_OVERRIDE; 1.60 + 1.61 + NS_IMETHOD AppendElementStart(mozilla::dom::Element* aElement, 1.62 + mozilla::dom::Element* aOriginalElement, 1.63 + nsAString& aStr) MOZ_OVERRIDE; 1.64 + 1.65 + NS_IMETHOD AppendElementEnd(mozilla::dom::Element* aElement, 1.66 + nsAString& aStr) MOZ_OVERRIDE; 1.67 + 1.68 + NS_IMETHOD Flush(nsAString& aStr) MOZ_OVERRIDE { return NS_OK; } 1.69 + 1.70 + NS_IMETHOD AppendDocumentStart(nsIDocument *aDocument, 1.71 + nsAString& aStr) MOZ_OVERRIDE; 1.72 + 1.73 + protected: 1.74 + 1.75 + /** 1.76 + * Appends a char16_t character and increments the column position 1.77 + */ 1.78 + void AppendToString(const char16_t aChar, 1.79 + nsAString& aOutputStr); 1.80 + 1.81 + /** 1.82 + * Appends a nsAString string and increments the column position 1.83 + */ 1.84 + void AppendToString(const nsAString& aStr, 1.85 + nsAString& aOutputStr); 1.86 + 1.87 + /** 1.88 + * Appends a string by replacing all line-endings 1.89 + * by mLineBreak, except in the case of raw output. 1.90 + * It increments the column position. 1.91 + */ 1.92 + void AppendToStringConvertLF(const nsAString& aStr, 1.93 + nsAString& aOutputStr); 1.94 + 1.95 + /** 1.96 + * Appends a string by wrapping it when necessary. 1.97 + * It updates the column position. 1.98 + */ 1.99 + void AppendToStringWrapped(const nsASingleFragmentString& aStr, 1.100 + nsAString& aOutputStr); 1.101 + 1.102 + /** 1.103 + * Appends a string by formating and wrapping it when necessary 1.104 + * It updates the column position. 1.105 + */ 1.106 + void AppendToStringFormatedWrapped(const nsASingleFragmentString& aStr, 1.107 + nsAString& aOutputStr); 1.108 + 1.109 + // used by AppendToStringWrapped 1.110 + void AppendWrapped_WhitespaceSequence( 1.111 + nsASingleFragmentString::const_char_iterator &aPos, 1.112 + const nsASingleFragmentString::const_char_iterator aEnd, 1.113 + const nsASingleFragmentString::const_char_iterator aSequenceStart, 1.114 + nsAString &aOutputStr); 1.115 + 1.116 + // used by AppendToStringFormatedWrapped 1.117 + void AppendFormatedWrapped_WhitespaceSequence( 1.118 + nsASingleFragmentString::const_char_iterator &aPos, 1.119 + const nsASingleFragmentString::const_char_iterator aEnd, 1.120 + const nsASingleFragmentString::const_char_iterator aSequenceStart, 1.121 + bool &aMayIgnoreStartOfLineWhitespaceSequence, 1.122 + nsAString &aOutputStr); 1.123 + 1.124 + // used by AppendToStringWrapped and AppendToStringFormatedWrapped 1.125 + void AppendWrapped_NonWhitespaceSequence( 1.126 + nsASingleFragmentString::const_char_iterator &aPos, 1.127 + const nsASingleFragmentString::const_char_iterator aEnd, 1.128 + const nsASingleFragmentString::const_char_iterator aSequenceStart, 1.129 + bool &aMayIgnoreStartOfLineWhitespaceSequence, 1.130 + bool &aSequenceStartAfterAWhiteSpace, 1.131 + nsAString &aOutputStr); 1.132 + 1.133 + /** 1.134 + * add mLineBreak to the string 1.135 + * It updates the column position and other flags. 1.136 + */ 1.137 + void AppendNewLineToString(nsAString& aOutputStr); 1.138 + 1.139 + 1.140 + /** 1.141 + * Appends a string by translating entities 1.142 + * It doesn't increment the column position 1.143 + */ 1.144 + virtual void AppendAndTranslateEntities(const nsAString& aStr, 1.145 + nsAString& aOutputStr); 1.146 + 1.147 + /** 1.148 + * retrieve the text content of the node and append it to the given string 1.149 + * It doesn't increment the column position 1.150 + */ 1.151 + nsresult AppendTextData(nsIContent* aNode, 1.152 + int32_t aStartOffset, 1.153 + int32_t aEndOffset, 1.154 + nsAString& aStr, 1.155 + bool aTranslateEntities); 1.156 + 1.157 + virtual nsresult PushNameSpaceDecl(const nsAString& aPrefix, 1.158 + const nsAString& aURI, 1.159 + nsIContent* aOwner); 1.160 + void PopNameSpaceDeclsFor(nsIContent* aOwner); 1.161 + 1.162 + /** 1.163 + * The problem that ConfirmPrefix fixes is that anyone can insert nodes 1.164 + * through the DOM that have a namespace URI and a random or empty or 1.165 + * previously existing prefix that's totally unrelated to the prefixes 1.166 + * declared at that point through xmlns attributes. So what ConfirmPrefix 1.167 + * does is ensure that we can map aPrefix to the namespace URI aURI (for 1.168 + * example, that the prefix is not already mapped to some other namespace). 1.169 + * aPrefix will be adjusted, if necessary, so the value of the prefix 1.170 + * _after_ this call is what should be serialized. 1.171 + * @param aPrefix the prefix that may need adjusting 1.172 + * @param aURI the namespace URI we want aPrefix to point to 1.173 + * @param aElement the element we're working with (needed for proper default 1.174 + * namespace handling) 1.175 + * @param aIsAttribute true if we're confirming a prefix for an attribute. 1.176 + * @return true if we need to push the (prefix, uri) pair on the namespace 1.177 + * stack (note that this can happen even if the prefix is 1.178 + * empty). 1.179 + */ 1.180 + bool ConfirmPrefix(nsAString& aPrefix, 1.181 + const nsAString& aURI, 1.182 + nsIContent* aElement, 1.183 + bool aIsAttribute); 1.184 + /** 1.185 + * GenerateNewPrefix generates a new prefix and writes it to aPrefix 1.186 + */ 1.187 + void GenerateNewPrefix(nsAString& aPrefix); 1.188 + 1.189 + uint32_t ScanNamespaceDeclarations(nsIContent* aContent, 1.190 + nsIContent *aOriginalElement, 1.191 + const nsAString& aTagNamespaceURI); 1.192 + 1.193 + virtual void SerializeAttributes(nsIContent* aContent, 1.194 + nsIContent *aOriginalElement, 1.195 + nsAString& aTagPrefix, 1.196 + const nsAString& aTagNamespaceURI, 1.197 + nsIAtom* aTagName, 1.198 + nsAString& aStr, 1.199 + uint32_t aSkipAttr, 1.200 + bool aAddNSAttr); 1.201 + 1.202 + void SerializeAttr(const nsAString& aPrefix, 1.203 + const nsAString& aName, 1.204 + const nsAString& aValue, 1.205 + nsAString& aStr, 1.206 + bool aDoEscapeEntities); 1.207 + 1.208 + bool IsJavaScript(nsIContent * aContent, 1.209 + nsIAtom* aAttrNameAtom, 1.210 + int32_t aAttrNamespaceID, 1.211 + const nsAString& aValueString); 1.212 + 1.213 + /** 1.214 + * This method can be redefined to check if the element can be serialized. 1.215 + * It is called when the serialization of the start tag is asked 1.216 + * (AppendElementStart) 1.217 + * In this method you can also force the formating 1.218 + * by setting aForceFormat to true. 1.219 + * @return boolean true if the element can be output 1.220 + */ 1.221 + virtual bool CheckElementStart(nsIContent * aContent, 1.222 + bool & aForceFormat, 1.223 + nsAString& aStr); 1.224 + 1.225 + /** 1.226 + * this method is responsible to finish the start tag, 1.227 + * in particulary to append the "greater than" sign 1.228 + */ 1.229 + virtual void AppendEndOfElementStart(nsIContent *aOriginalElement, 1.230 + nsIAtom * aName, 1.231 + int32_t aNamespaceID, 1.232 + nsAString& aStr); 1.233 + 1.234 + /** 1.235 + * This method can be redefine to serialize additional things just after 1.236 + * after the serialization ot the start tag. 1.237 + * (called at the end of AppendElementStart) 1.238 + */ 1.239 + virtual void AfterElementStart(nsIContent * aContent, 1.240 + nsIContent *aOriginalElement, 1.241 + nsAString& aStr) { }; 1.242 + 1.243 + /** 1.244 + * This method can be redefined to check if the element can be serialized. 1.245 + * It is called when the serialization of the end tag is asked 1.246 + * (AppendElementEnd) 1.247 + * In this method you can also force the formating 1.248 + * by setting aForceFormat to true. 1.249 + * @return boolean true if the element can be output 1.250 + */ 1.251 + virtual bool CheckElementEnd(nsIContent * aContent, 1.252 + bool & aForceFormat, 1.253 + nsAString& aStr); 1.254 + 1.255 + /** 1.256 + * This method can be redefine to serialize additional things just after 1.257 + * after the serialization ot the end tag. 1.258 + * (called at the end of AppendElementStart) 1.259 + */ 1.260 + virtual void AfterElementEnd(nsIContent * aContent, 1.261 + nsAString& aStr) { }; 1.262 + 1.263 + /** 1.264 + * Returns true if a line break should be inserted before an element open tag 1.265 + */ 1.266 + virtual bool LineBreakBeforeOpen(int32_t aNamespaceID, nsIAtom* aName); 1.267 + 1.268 + /** 1.269 + * Returns true if a line break should be inserted after an element open tag 1.270 + */ 1.271 + virtual bool LineBreakAfterOpen(int32_t aNamespaceID, nsIAtom* aName); 1.272 + 1.273 + /** 1.274 + * Returns true if a line break should be inserted after an element close tag 1.275 + */ 1.276 + virtual bool LineBreakBeforeClose(int32_t aNamespaceID, nsIAtom* aName); 1.277 + 1.278 + /** 1.279 + * Returns true if a line break should be inserted after an element close tag 1.280 + */ 1.281 + virtual bool LineBreakAfterClose(int32_t aNamespaceID, nsIAtom* aName); 1.282 + 1.283 + /** 1.284 + * add intendation. Call only in the case of formating and if the current 1.285 + * position is at 0. It updates the column position. 1.286 + */ 1.287 + void AppendIndentation(nsAString& aStr); 1.288 + void IncrIndentation(nsIAtom* aName); 1.289 + void DecrIndentation(nsIAtom* aName); 1.290 + 1.291 + // Functions to check for newlines that needs to be added between nodes in 1.292 + // the root of a document. See mAddNewlineForRootNode 1.293 + void MaybeAddNewlineForRootNode(nsAString& aStr); 1.294 + void MaybeFlagNewlineForRootNode(nsINode* aNode); 1.295 + 1.296 + // Functions to check if we enter in or leave from a preformated content 1.297 + virtual void MaybeEnterInPreContent(nsIContent* aNode); 1.298 + virtual void MaybeLeaveFromPreContent(nsIContent* aNode); 1.299 + 1.300 + int32_t mPrefixIndex; 1.301 + 1.302 + struct NameSpaceDecl { 1.303 + nsString mPrefix; 1.304 + nsString mURI; 1.305 + nsIContent* mOwner; 1.306 + }; 1.307 + 1.308 + nsTArray<NameSpaceDecl> mNameSpaceStack; 1.309 + 1.310 + // nsIDocumentEncoder flags 1.311 + uint32_t mFlags; 1.312 + 1.313 + // characters to use for line break 1.314 + nsString mLineBreak; 1.315 + 1.316 + // The charset that was passed to Init() 1.317 + nsCString mCharset; 1.318 + 1.319 + // current column position on the current line 1.320 + uint32_t mColPos; 1.321 + 1.322 + // true = pretty formating should be done (OutputFormated flag) 1.323 + bool mDoFormat; 1.324 + 1.325 + // true = no formatting,(OutputRaw flag) 1.326 + // no newline convertion and no rewrap long lines even if OutputWrap is set. 1.327 + bool mDoRaw; 1.328 + 1.329 + // true = wrapping should be done (OutputWrap flag) 1.330 + bool mDoWrap; 1.331 + 1.332 + // number of maximum column in a line, in the wrap mode 1.333 + uint32_t mMaxColumn; 1.334 + 1.335 + // current indent value 1.336 + nsString mIndent; 1.337 + 1.338 + // this is the indentation level after the indentation reached 1.339 + // the maximum length of indentation 1.340 + int32_t mIndentOverflow; 1.341 + 1.342 + // says if the indentation has been already added on the current line 1.343 + bool mIsIndentationAddedOnCurrentLine; 1.344 + 1.345 + // the string which is currently added is in an attribute 1.346 + bool mInAttribute; 1.347 + 1.348 + // true = a newline character should be added. It's only 1.349 + // useful when serializing root nodes. see MaybeAddNewlineForRootNode and 1.350 + // MaybeFlagNewlineForRootNode 1.351 + bool mAddNewlineForRootNode; 1.352 + 1.353 + // Indicates that a space will be added if and only if content is 1.354 + // continued on the same line while serializing source. Otherwise, 1.355 + // the newline character acts as the whitespace and no space is needed. 1.356 + // used when mDoFormat = true 1.357 + bool mAddSpace; 1.358 + 1.359 + // says that if the next string to add contains a newline character at the 1.360 + // begining, then this newline character should be ignored, because a 1.361 + // such character has already been added into the output string 1.362 + bool mMayIgnoreLineBreakSequence; 1.363 + 1.364 + bool mBodyOnly; 1.365 + int32_t mInBody; 1.366 + 1.367 + // number of nested elements which have preformated content 1.368 + int32_t mPreLevel; 1.369 +}; 1.370 + 1.371 +nsresult 1.372 +NS_NewXMLContentSerializer(nsIContentSerializer** aSerializer); 1.373 + 1.374 +#endif