Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsIInputStream.h"
7 #include "nsNetCID.h"
8 #include "nsNetUtil.h"
9 #include "nsIParser.h"
10 #include "nsParserCIID.h"
11 #include "nsStreamUtils.h"
12 #include "nsStringStream.h"
13 #include "nsIScriptError.h"
14 #include "nsSAXAttributes.h"
15 #include "nsSAXLocator.h"
16 #include "nsSAXXMLReader.h"
17 #include "nsCharsetSource.h"
19 #include "mozilla/dom/EncodingUtils.h"
21 using mozilla::dom::EncodingUtils;
23 #define XMLNS_URI "http://www.w3.org/2000/xmlns/"
25 static NS_DEFINE_CID(kParserCID, NS_PARSER_CID);
27 NS_IMPL_CYCLE_COLLECTION(nsSAXXMLReader,
28 mContentHandler,
29 mDTDHandler,
30 mErrorHandler,
31 mLexicalHandler,
32 mDeclarationHandler,
33 mBaseURI,
34 mListener,
35 mParserObserver)
36 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSAXXMLReader)
37 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSAXXMLReader)
38 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSAXXMLReader)
39 NS_INTERFACE_MAP_ENTRY(nsISAXXMLReader)
40 NS_INTERFACE_MAP_ENTRY(nsIExpatSink)
41 NS_INTERFACE_MAP_ENTRY(nsIExtendedExpatSink)
42 NS_INTERFACE_MAP_ENTRY(nsIContentSink)
43 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
44 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
45 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISAXXMLReader)
46 NS_INTERFACE_MAP_END
48 nsSAXXMLReader::nsSAXXMLReader() :
49 mIsAsyncParse(false),
50 mEnableNamespacePrefixes(false)
51 {
52 }
54 // nsIContentSink
55 NS_IMETHODIMP
56 nsSAXXMLReader::WillBuildModel(nsDTDMode)
57 {
58 if (mContentHandler)
59 return mContentHandler->StartDocument();
61 return NS_OK;
62 }
64 NS_IMETHODIMP
65 nsSAXXMLReader::DidBuildModel(bool aTerminated)
66 {
67 if (mContentHandler)
68 return mContentHandler->EndDocument();
70 return NS_OK;
71 }
73 NS_IMETHODIMP
74 nsSAXXMLReader::SetParser(nsParserBase *aParser)
75 {
76 return NS_OK;
77 }
79 // nsIExtendedExpatSink
80 NS_IMETHODIMP
81 nsSAXXMLReader::HandleStartElement(const char16_t *aName,
82 const char16_t **aAtts,
83 uint32_t aAttsCount,
84 int32_t aIndex,
85 uint32_t aLineNumber)
86 {
87 if (!mContentHandler)
88 return NS_OK;
90 nsRefPtr<nsSAXAttributes> atts = new nsSAXAttributes();
91 if (!atts)
92 return NS_ERROR_OUT_OF_MEMORY;
93 nsAutoString uri, localName, qName;
94 for (; *aAtts; aAtts += 2) {
95 SplitExpatName(aAtts[0], uri, localName, qName);
96 // XXX don't have attr type information
97 NS_NAMED_LITERAL_STRING(cdataType, "CDATA");
98 // could support xmlns reporting, it's a standard SAX feature
99 if (mEnableNamespacePrefixes || !uri.EqualsLiteral(XMLNS_URI)) {
100 NS_ASSERTION(aAtts[1], "null passed to handler");
101 atts->AddAttribute(uri, localName, qName, cdataType,
102 nsDependentString(aAtts[1]));
103 }
104 }
106 // Deal with the element name
107 SplitExpatName(aName, uri, localName, qName);
108 return mContentHandler->StartElement(uri, localName, qName, atts);
109 }
111 NS_IMETHODIMP
112 nsSAXXMLReader::HandleEndElement(const char16_t *aName)
113 {
114 if (mContentHandler) {
115 nsAutoString uri, localName, qName;
116 SplitExpatName(aName, uri, localName, qName);
117 return mContentHandler->EndElement(uri, localName, qName);
118 }
119 return NS_OK;
120 }
122 NS_IMETHODIMP
123 nsSAXXMLReader::HandleComment(const char16_t *aName)
124 {
125 NS_ASSERTION(aName, "null passed to handler");
126 if (mLexicalHandler)
127 return mLexicalHandler->Comment(nsDependentString(aName));
129 return NS_OK;
130 }
132 NS_IMETHODIMP
133 nsSAXXMLReader::HandleCDataSection(const char16_t *aData,
134 uint32_t aLength)
135 {
136 nsresult rv;
137 if (mLexicalHandler) {
138 rv = mLexicalHandler->StartCDATA();
139 NS_ENSURE_SUCCESS(rv, rv);
140 }
142 if (mContentHandler) {
143 rv = mContentHandler->Characters(Substring(aData, aData+aLength));
144 NS_ENSURE_SUCCESS(rv, rv);
145 }
147 if (mLexicalHandler) {
148 rv = mLexicalHandler->EndCDATA();
149 NS_ENSURE_SUCCESS(rv, rv);
150 }
152 return NS_OK;
153 }
155 NS_IMETHODIMP
156 nsSAXXMLReader::HandleStartDTD(const char16_t *aName,
157 const char16_t *aSystemId,
158 const char16_t *aPublicId)
159 {
160 char16_t nullChar = char16_t(0);
161 if (!aName)
162 aName = &nullChar;
163 if (!aSystemId)
164 aSystemId = &nullChar;
165 if (!aPublicId)
166 aPublicId = &nullChar;
168 mSystemId = aSystemId;
169 mPublicId = aPublicId;
170 if (mLexicalHandler) {
171 return mLexicalHandler->StartDTD(nsDependentString(aName),
172 nsDependentString(aPublicId),
173 nsDependentString(aSystemId));
174 }
176 return NS_OK;
177 }
179 NS_IMETHODIMP
180 nsSAXXMLReader::HandleDoctypeDecl(const nsAString & aSubset,
181 const nsAString & aName,
182 const nsAString & aSystemId,
183 const nsAString & aPublicId,
184 nsISupports* aCatalogData)
185 {
186 if (mLexicalHandler)
187 return mLexicalHandler->EndDTD();
189 return NS_OK;
190 }
192 NS_IMETHODIMP
193 nsSAXXMLReader::HandleCharacterData(const char16_t *aData,
194 uint32_t aLength)
195 {
196 if (mContentHandler)
197 return mContentHandler->Characters(Substring(aData, aData+aLength));
199 return NS_OK;
200 }
202 NS_IMETHODIMP
203 nsSAXXMLReader::HandleStartNamespaceDecl(const char16_t *aPrefix,
204 const char16_t *aUri)
205 {
206 if (!mContentHandler)
207 return NS_OK;
209 char16_t nullChar = char16_t(0);
210 if (!aPrefix)
211 aPrefix = &nullChar;
212 if (!aUri)
213 aUri = &nullChar;
215 return mContentHandler->StartPrefixMapping(nsDependentString(aPrefix),
216 nsDependentString(aUri));
217 }
219 NS_IMETHODIMP
220 nsSAXXMLReader::HandleEndNamespaceDecl(const char16_t *aPrefix)
221 {
222 if (!mContentHandler)
223 return NS_OK;
225 if (aPrefix)
226 return mContentHandler->EndPrefixMapping(nsDependentString(aPrefix));
228 return mContentHandler->EndPrefixMapping(EmptyString());
229 }
231 NS_IMETHODIMP
232 nsSAXXMLReader::HandleProcessingInstruction(const char16_t *aTarget,
233 const char16_t *aData)
234 {
235 NS_ASSERTION(aTarget && aData, "null passed to handler");
236 if (mContentHandler) {
237 return mContentHandler->ProcessingInstruction(nsDependentString(aTarget),
238 nsDependentString(aData));
239 }
241 return NS_OK;
242 }
244 NS_IMETHODIMP
245 nsSAXXMLReader::HandleNotationDecl(const char16_t *aNotationName,
246 const char16_t *aSystemId,
247 const char16_t *aPublicId)
248 {
249 NS_ASSERTION(aNotationName, "null passed to handler");
250 if (mDTDHandler) {
251 char16_t nullChar = char16_t(0);
252 if (!aSystemId)
253 aSystemId = &nullChar;
254 if (!aPublicId)
255 aPublicId = &nullChar;
257 return mDTDHandler->NotationDecl(nsDependentString(aNotationName),
258 nsDependentString(aSystemId),
259 nsDependentString(aPublicId));
260 }
262 return NS_OK;
263 }
265 NS_IMETHODIMP
266 nsSAXXMLReader::HandleUnparsedEntityDecl(const char16_t *aEntityName,
267 const char16_t *aSystemId,
268 const char16_t *aPublicId,
269 const char16_t *aNotationName)
270 {
271 NS_ASSERTION(aEntityName && aNotationName, "null passed to handler");
272 if (mDTDHandler) {
273 char16_t nullChar = char16_t(0);
274 if (!aSystemId)
275 aSystemId = &nullChar;
276 if (!aPublicId)
277 aPublicId = &nullChar;
279 return mDTDHandler->UnparsedEntityDecl(nsDependentString(aEntityName),
280 nsDependentString(aSystemId),
281 nsDependentString(aPublicId),
282 nsDependentString(aNotationName));
283 }
285 return NS_OK;
286 }
288 NS_IMETHODIMP
289 nsSAXXMLReader::HandleXMLDeclaration(const char16_t *aVersion,
290 const char16_t *aEncoding,
291 int32_t aStandalone)
292 {
293 NS_ASSERTION(aVersion, "null passed to handler");
294 if (mDeclarationHandler) {
295 char16_t nullChar = char16_t(0);
296 if (!aEncoding)
297 aEncoding = &nullChar;
298 mDeclarationHandler->HandleXMLDeclaration(nsDependentString(aVersion),
299 nsDependentString(aEncoding),
300 aStandalone > 0);
301 }
302 return NS_OK;
303 }
305 NS_IMETHODIMP
306 nsSAXXMLReader::ReportError(const char16_t* aErrorText,
307 const char16_t* aSourceText,
308 nsIScriptError *aError,
309 bool *_retval)
310 {
311 NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!");
312 // Normally, the expat driver should report the error.
313 *_retval = true;
315 if (mErrorHandler) {
316 uint32_t lineNumber;
317 nsresult rv = aError->GetLineNumber(&lineNumber);
318 NS_ENSURE_SUCCESS(rv, rv);
320 uint32_t columnNumber;
321 rv = aError->GetColumnNumber(&columnNumber);
322 NS_ENSURE_SUCCESS(rv, rv);
324 nsCOMPtr<nsISAXLocator> locator = new nsSAXLocator(mPublicId,
325 mSystemId,
326 lineNumber,
327 columnNumber);
328 if (!locator)
329 return NS_ERROR_OUT_OF_MEMORY;
331 rv = mErrorHandler->FatalError(locator, nsDependentString(aErrorText));
332 if (NS_SUCCEEDED(rv)) {
333 // The error handler has handled the script error. Don't log to console.
334 *_retval = false;
335 }
336 }
338 return NS_OK;
339 }
341 // nsISAXXMLReader
343 NS_IMETHODIMP
344 nsSAXXMLReader::GetBaseURI(nsIURI **aBaseURI)
345 {
346 NS_IF_ADDREF(*aBaseURI = mBaseURI);
347 return NS_OK;
348 }
350 NS_IMETHODIMP
351 nsSAXXMLReader::SetBaseURI(nsIURI *aBaseURI)
352 {
353 mBaseURI = aBaseURI;
354 return NS_OK;
355 }
357 NS_IMETHODIMP
358 nsSAXXMLReader::GetContentHandler(nsISAXContentHandler **aContentHandler)
359 {
360 NS_IF_ADDREF(*aContentHandler = mContentHandler);
361 return NS_OK;
362 }
364 NS_IMETHODIMP
365 nsSAXXMLReader::SetContentHandler(nsISAXContentHandler *aContentHandler)
366 {
367 mContentHandler = aContentHandler;
368 return NS_OK;
369 }
371 NS_IMETHODIMP
372 nsSAXXMLReader::GetDtdHandler(nsISAXDTDHandler **aDtdHandler)
373 {
374 NS_IF_ADDREF(*aDtdHandler = mDTDHandler);
375 return NS_OK;
376 }
378 NS_IMETHODIMP
379 nsSAXXMLReader::SetDtdHandler(nsISAXDTDHandler *aDtdHandler)
380 {
381 mDTDHandler = aDtdHandler;
382 return NS_OK;
383 }
385 NS_IMETHODIMP
386 nsSAXXMLReader::GetErrorHandler(nsISAXErrorHandler **aErrorHandler)
387 {
388 NS_IF_ADDREF(*aErrorHandler = mErrorHandler);
389 return NS_OK;
390 }
392 NS_IMETHODIMP
393 nsSAXXMLReader::SetErrorHandler(nsISAXErrorHandler *aErrorHandler)
394 {
395 mErrorHandler = aErrorHandler;
396 return NS_OK;
397 }
399 NS_IMETHODIMP
400 nsSAXXMLReader::SetFeature(const nsAString &aName, bool aValue)
401 {
402 if (aName.EqualsLiteral("http://xml.org/sax/features/namespace-prefixes")) {
403 mEnableNamespacePrefixes = aValue;
404 return NS_OK;
405 }
406 return NS_ERROR_NOT_IMPLEMENTED;
407 }
409 NS_IMETHODIMP
410 nsSAXXMLReader::GetFeature(const nsAString &aName, bool *aResult)
411 {
412 if (aName.EqualsLiteral("http://xml.org/sax/features/namespace-prefixes")) {
413 *aResult = mEnableNamespacePrefixes;
414 return NS_OK;
415 }
416 return NS_ERROR_NOT_IMPLEMENTED;
417 }
419 NS_IMETHODIMP
420 nsSAXXMLReader::GetDeclarationHandler(nsIMozSAXXMLDeclarationHandler **aDeclarationHandler) {
421 NS_IF_ADDREF(*aDeclarationHandler = mDeclarationHandler);
422 return NS_OK;
423 }
425 NS_IMETHODIMP
426 nsSAXXMLReader::SetDeclarationHandler(nsIMozSAXXMLDeclarationHandler *aDeclarationHandler) {
427 mDeclarationHandler = aDeclarationHandler;
428 return NS_OK;
429 }
431 NS_IMETHODIMP
432 nsSAXXMLReader::GetLexicalHandler(nsISAXLexicalHandler **aLexicalHandler)
433 {
434 NS_IF_ADDREF(*aLexicalHandler = mLexicalHandler);
435 return NS_OK;
436 }
438 NS_IMETHODIMP
439 nsSAXXMLReader::SetLexicalHandler(nsISAXLexicalHandler *aLexicalHandler)
440 {
441 mLexicalHandler = aLexicalHandler;
442 return NS_OK;
443 }
445 NS_IMETHODIMP
446 nsSAXXMLReader::SetProperty(const nsAString &aName, nsISupports* aValue)
447 {
448 return NS_ERROR_NOT_IMPLEMENTED;
449 }
451 NS_IMETHODIMP
452 nsSAXXMLReader::GetProperty(const nsAString &aName, bool *aResult)
453 {
454 return NS_ERROR_NOT_IMPLEMENTED;
455 }
457 NS_IMETHODIMP
458 nsSAXXMLReader::ParseFromString(const nsAString &aStr,
459 const char *aContentType)
460 {
461 // Don't call this in the middle of an async parse
462 NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
464 NS_ConvertUTF16toUTF8 data(aStr);
466 // The new stream holds a reference to the buffer
467 nsCOMPtr<nsIInputStream> stream;
468 nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
469 data.get(), data.Length(),
470 NS_ASSIGNMENT_DEPEND);
471 NS_ENSURE_SUCCESS(rv, rv);
472 return ParseFromStream(stream, "UTF-8", aContentType);
473 }
475 NS_IMETHODIMP
476 nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
477 const char *aCharset,
478 const char *aContentType)
479 {
480 // Don't call this in the middle of an async parse
481 NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
483 NS_ENSURE_ARG(aStream);
484 NS_ENSURE_ARG(aContentType);
486 // Put the nsCOMPtr out here so we hold a ref to the stream as needed
487 nsresult rv;
488 nsCOMPtr<nsIInputStream> bufferedStream;
489 if (!NS_InputStreamIsBuffered(aStream)) {
490 rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
491 aStream, 4096);
492 NS_ENSURE_SUCCESS(rv, rv);
493 aStream = bufferedStream;
494 }
496 rv = EnsureBaseURI();
497 NS_ENSURE_SUCCESS(rv, rv);
499 nsCOMPtr<nsIChannel> parserChannel;
500 rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel), mBaseURI,
501 aStream, nsDependentCString(aContentType));
502 if (!parserChannel || NS_FAILED(rv))
503 return NS_ERROR_FAILURE;
505 if (aCharset)
506 parserChannel->SetContentCharset(nsDependentCString(aCharset));
508 rv = InitParser(nullptr, parserChannel);
509 NS_ENSURE_SUCCESS(rv, rv);
511 rv = mListener->OnStartRequest(parserChannel, nullptr);
512 if (NS_FAILED(rv))
513 parserChannel->Cancel(rv);
515 /* When parsing a new document, we need to clear the XML identifiers.
516 HandleStartDTD will set these values from the DTD declaration tag.
517 We won't have them, of course, if there's a well-formedness error
518 before the DTD tag (such as a space before an XML declaration).
519 */
520 mSystemId.Truncate();
521 mPublicId.Truncate();
523 nsresult status;
524 parserChannel->GetStatus(&status);
526 uint64_t offset = 0;
527 while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
528 uint64_t available;
529 rv = aStream->Available(&available);
530 if (rv == NS_BASE_STREAM_CLOSED) {
531 rv = NS_OK;
532 available = 0;
533 }
534 if (NS_FAILED(rv)) {
535 parserChannel->Cancel(rv);
536 break;
537 }
538 if (! available)
539 break; // blocking input stream has none available when done
541 if (available > UINT32_MAX)
542 available = UINT32_MAX;
544 rv = mListener->OnDataAvailable(parserChannel, nullptr,
545 aStream,
546 offset,
547 (uint32_t)available);
548 if (NS_SUCCEEDED(rv))
549 offset += available;
550 else
551 parserChannel->Cancel(rv);
552 parserChannel->GetStatus(&status);
553 }
554 rv = mListener->OnStopRequest(parserChannel, nullptr, status);
555 mListener = nullptr;
557 return rv;
558 }
560 NS_IMETHODIMP
561 nsSAXXMLReader::ParseAsync(nsIRequestObserver *aObserver)
562 {
563 mParserObserver = aObserver;
564 mIsAsyncParse = true;
565 return NS_OK;
566 }
568 // nsIRequestObserver
570 NS_IMETHODIMP
571 nsSAXXMLReader::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
572 {
573 NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
574 nsresult rv;
575 rv = EnsureBaseURI();
576 NS_ENSURE_SUCCESS(rv, rv);
577 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
578 rv = InitParser(mParserObserver, channel);
579 NS_ENSURE_SUCCESS(rv, rv);
580 // we don't need or want this anymore
581 mParserObserver = nullptr;
582 return mListener->OnStartRequest(aRequest, aContext);
583 }
585 NS_IMETHODIMP
586 nsSAXXMLReader::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
587 nsresult status)
588 {
589 NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
590 NS_ENSURE_STATE(mListener);
591 nsresult rv = mListener->OnStopRequest(aRequest, aContext, status);
592 mListener = nullptr;
593 mIsAsyncParse = false;
594 return rv;
595 }
597 // nsIStreamListener
599 NS_IMETHODIMP
600 nsSAXXMLReader::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext,
601 nsIInputStream *aInputStream, uint64_t offset,
602 uint32_t count)
603 {
604 NS_ENSURE_TRUE(mIsAsyncParse, NS_ERROR_FAILURE);
605 NS_ENSURE_STATE(mListener);
606 return mListener->OnDataAvailable(aRequest, aContext, aInputStream, offset,
607 count);
608 }
610 nsresult
611 nsSAXXMLReader::InitParser(nsIRequestObserver *aObserver, nsIChannel *aChannel)
612 {
613 nsresult rv;
615 // setup the parser
616 nsCOMPtr<nsIParser> parser = do_CreateInstance(kParserCID, &rv);
617 NS_ENSURE_SUCCESS(rv, rv);
619 parser->SetContentSink(this);
621 int32_t charsetSource = kCharsetFromDocTypeDefault;
622 nsAutoCString charset(NS_LITERAL_CSTRING("UTF-8"));
623 TryChannelCharset(aChannel, charsetSource, charset);
624 parser->SetDocumentCharset(charset, charsetSource);
626 rv = parser->Parse(mBaseURI, aObserver);
627 NS_ENSURE_SUCCESS(rv, rv);
629 mListener = do_QueryInterface(parser, &rv);
631 return rv;
632 }
634 // from nsDocument.cpp
635 bool
636 nsSAXXMLReader::TryChannelCharset(nsIChannel *aChannel,
637 int32_t& aCharsetSource,
638 nsACString& aCharset)
639 {
640 if (aCharsetSource >= kCharsetFromChannel)
641 return true;
643 if (aChannel) {
644 nsAutoCString charsetVal;
645 nsresult rv = aChannel->GetContentCharset(charsetVal);
646 if (NS_SUCCEEDED(rv)) {
647 nsAutoCString preferred;
648 if (!EncodingUtils::FindEncodingForLabel(charsetVal, preferred))
649 return false;
651 aCharset = preferred;
652 aCharsetSource = kCharsetFromChannel;
653 return true;
654 }
655 }
657 return false;
658 }
660 nsresult
661 nsSAXXMLReader::EnsureBaseURI()
662 {
663 if (mBaseURI)
664 return NS_OK;
666 return NS_NewURI(getter_AddRefs(mBaseURI), "about:blank");
667 }
669 nsresult
670 nsSAXXMLReader::SplitExpatName(const char16_t *aExpatName,
671 nsString &aURI,
672 nsString &aLocalName,
673 nsString &aQName)
674 {
675 /**
676 * Adapted from RDFContentSinkImpl
677 *
678 * Expat can send the following:
679 * localName
680 * namespaceURI<separator>localName
681 * namespaceURI<separator>localName<separator>prefix
682 *
683 * and we use 0xFFFF for the <separator>.
684 *
685 */
687 NS_ASSERTION(aExpatName, "null passed to handler");
688 nsDependentString expatStr(aExpatName);
689 int32_t break1, break2 = kNotFound;
690 break1 = expatStr.FindChar(char16_t(0xFFFF));
692 if (break1 == kNotFound) {
693 aLocalName = expatStr; // no namespace
694 aURI.Truncate();
695 aQName = expatStr;
696 } else {
697 aURI = StringHead(expatStr, break1);
698 break2 = expatStr.FindChar(char16_t(0xFFFF), break1 + 1);
699 if (break2 == kNotFound) { // namespace, but no prefix
700 aLocalName = Substring(expatStr, break1 + 1);
701 aQName = aLocalName;
702 } else { // namespace with prefix
703 aLocalName = Substring(expatStr, break1 + 1, break2 - break1 - 1);
704 aQName = Substring(expatStr, break2 + 1) +
705 NS_LITERAL_STRING(":") + aLocalName;
706 }
707 }
709 return NS_OK;
710 }