summaryrefslogtreecommitdiffstats
path: root/dom/xml
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /dom/xml
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/xml')
-rw-r--r--dom/xml/CDATASection.cpp50
-rw-r--r--dom/xml/CDATASection.h56
-rw-r--r--dom/xml/ProcessingInstruction.cpp107
-rw-r--r--dom/xml/ProcessingInstruction.h74
-rw-r--r--dom/xml/XMLDocument.cpp338
-rw-r--r--dom/xml/XMLDocument.h86
-rw-r--r--dom/xml/XMLStylesheetProcessingInstruction.cpp157
-rw-r--r--dom/xml/XMLStylesheetProcessingInstruction.h84
-rw-r--r--dom/xml/crashtests/1038887.xhtml1
-rw-r--r--dom/xml/crashtests/136896-1.xml62
-rw-r--r--dom/xml/crashtests/1405878.xml11
-rw-r--r--dom/xml/crashtests/1523655.xml3
-rw-r--r--dom/xml/crashtests/185285-1.xml2
-rw-r--r--dom/xml/crashtests/382636-1.xml9
-rw-r--r--dom/xml/crashtests/382636-2.svg5
-rw-r--r--dom/xml/crashtests/382636-3.xhtml9
-rw-r--r--dom/xml/crashtests/382636-4.xhtml5
-rw-r--r--dom/xml/crashtests/420429.xhtml18
-rw-r--r--dom/xml/crashtests/431703-1.xhtml17
-rw-r--r--dom/xml/crashtests/453278-frame.xml3
-rw-r--r--dom/xml/crashtests/453278.html9
-rw-r--r--dom/xml/crashtests/803586.xhtml8
-rw-r--r--dom/xml/crashtests/994740-1.xhtml15
-rw-r--r--dom/xml/crashtests/crashtests.list14
-rw-r--r--dom/xml/crashtests/tree.gifbin0 -> 1140 bytes
-rw-r--r--dom/xml/htmlmathml-f.ent2164
-rw-r--r--dom/xml/moz.build51
-rw-r--r--dom/xml/nsIXMLContentSink.h61
-rw-r--r--dom/xml/nsXMLContentSink.cpp1536
-rw-r--r--dom/xml/nsXMLContentSink.h217
-rw-r--r--dom/xml/nsXMLElement.cpp54
-rw-r--r--dom/xml/nsXMLElement.h35
-rw-r--r--dom/xml/nsXMLFragmentContentSink.cpp372
-rw-r--r--dom/xml/nsXMLPrettyPrinter.cpp189
-rw-r--r--dom/xml/nsXMLPrettyPrinter.h59
-rw-r--r--dom/xml/resources/XMLPrettyPrint.css58
-rw-r--r--dom/xml/resources/XMLPrettyPrint.xsl133
-rw-r--r--dom/xml/resources/jar.mn7
-rw-r--r--dom/xml/resources/moz.build7
-rw-r--r--dom/xml/test/file_bug293347.xml2
-rw-r--r--dom/xml/test/file_bug293347xslt.xml19
-rw-r--r--dom/xml/test/file_bug343870.xml6
-rw-r--r--dom/xml/test/file_bug691215.xml2
-rw-r--r--dom/xml/test/mochitest.ini14
-rw-r--r--dom/xml/test/old/books/bethlehem.gifbin0 -> 5565 bytes
-rw-r--r--dom/xml/test/old/books/bill.gifbin0 -> 5022 bytes
-rw-r--r--dom/xml/test/old/books/books.js90
-rw-r--r--dom/xml/test/old/books/books.xml103
-rw-r--r--dom/xml/test/old/books/charing.gifbin0 -> 5947 bytes
-rw-r--r--dom/xml/test/old/books/classic.css78
-rw-r--r--dom/xml/test/old/books/common.css43
-rw-r--r--dom/xml/test/old/books/kerouac.gifbin0 -> 50387 bytes
-rw-r--r--dom/xml/test/old/books/list.css61
-rw-r--r--dom/xml/test/old/books/road.gifbin0 -> 8004 bytes
-rw-r--r--dom/xml/test/old/books/welville.gifbin0 -> 4535 bytes
-rw-r--r--dom/xml/test/old/docbook.css621
-rw-r--r--dom/xml/test/old/docbooktest.xml126
-rw-r--r--dom/xml/test/old/flamer.gifbin0 -> 11284 bytes
-rw-r--r--dom/xml/test/old/script.xml67
-rw-r--r--dom/xml/test/old/simple.xml10
-rw-r--r--dom/xml/test/old/toc/book.css137
-rw-r--r--dom/xml/test/old/toc/irslogo.gifbin0 -> 2605 bytes
-rw-r--r--dom/xml/test/old/toc/minus.gifbin0 -> 85 bytes
-rw-r--r--dom/xml/test/old/toc/plus.gifbin0 -> 88 bytes
-rw-r--r--dom/xml/test/old/toc/rights.xml292
-rw-r--r--dom/xml/test/old/toc/toc.css77
-rw-r--r--dom/xml/test/old/toc/toc.js131
-rw-r--r--dom/xml/test/old/xlink/auto.xml16
-rw-r--r--dom/xml/test/old/xlink/link.css22
-rw-r--r--dom/xml/test/old/xlink/manual.xml14
-rw-r--r--dom/xml/test/old/xmlbase/xmlbase.css28
-rw-r--r--dom/xml/test/old/xmlbase/xmlbase.xml82
-rw-r--r--dom/xml/test/test_bug232004.xhtml38
-rw-r--r--dom/xml/test/test_bug293347.html33
-rw-r--r--dom/xml/test/test_bug343870.xhtml39
-rw-r--r--dom/xml/test/test_bug355213.xhtml35
-rw-r--r--dom/xml/test/test_bug691215.html53
77 files changed, 8325 insertions, 0 deletions
diff --git a/dom/xml/CDATASection.cpp b/dom/xml/CDATASection.cpp
new file mode 100644
index 0000000000..4858c24af1
--- /dev/null
+++ b/dom/xml/CDATASection.cpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/CDATASection.h"
+#include "mozilla/dom/CDATASectionBinding.h"
+#include "mozilla/IntegerPrintfMacros.h"
+
+namespace mozilla::dom {
+
+CDATASection::~CDATASection() = default;
+
+JSObject* CDATASection::WrapNode(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) {
+ return CDATASection_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+already_AddRefed<CharacterData> CDATASection::CloneDataNode(
+ mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const {
+ RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
+ auto* nim = ni->NodeInfoManager();
+ RefPtr<CDATASection> it = new (nim) CDATASection(ni.forget());
+ if (aCloneText) {
+ it->mText = mText;
+ }
+
+ return it.forget();
+}
+
+#ifdef MOZ_DOM_LIST
+void CDATASection::List(FILE* out, int32_t aIndent) const {
+ int32_t index;
+ for (index = aIndent; --index >= 0;) fputs(" ", out);
+
+ fprintf(out, "CDATASection refcount=%" PRIuPTR "<", mRefCnt.get());
+
+ nsAutoString tmp;
+ ToCString(tmp, 0, mText.GetLength());
+ fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
+
+ fputs(">\n", out);
+}
+
+void CDATASection::DumpContent(FILE* out, int32_t aIndent,
+ bool aDumpAll) const {}
+#endif
+
+} // namespace mozilla::dom
diff --git a/dom/xml/CDATASection.h b/dom/xml/CDATASection.h
new file mode 100644
index 0000000000..ab20a2d21e
--- /dev/null
+++ b/dom/xml/CDATASection.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_CDATASection_h
+#define mozilla_dom_CDATASection_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/dom/Text.h"
+
+namespace mozilla::dom {
+
+class CDATASection final : public Text {
+ private:
+ void Init() {
+ MOZ_ASSERT(mNodeInfo->NodeType() == CDATA_SECTION_NODE,
+ "Bad NodeType in aNodeInfo");
+ }
+
+ virtual ~CDATASection();
+
+ public:
+ explicit CDATASection(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
+ : Text(std::move(aNodeInfo)) {
+ Init();
+ }
+
+ explicit CDATASection(nsNodeInfoManager* aNodeInfoManager)
+ : Text(aNodeInfoManager->GetNodeInfo(nsGkAtoms::cdataTagName, nullptr,
+ kNameSpaceID_None,
+ CDATA_SECTION_NODE)) {
+ Init();
+ }
+
+ // nsISupports
+ NS_INLINE_DECL_REFCOUNTING_INHERITED(CDATASection, Text)
+
+ // nsINode
+ already_AddRefed<CharacterData> CloneDataNode(
+ mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const override;
+
+#ifdef MOZ_DOM_LIST
+ void List(FILE* out, int32_t aIndent) const override;
+ void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override;
+#endif
+
+ protected:
+ JSObject* WrapNode(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) override;
+};
+
+} // namespace mozilla::dom
+
+#endif // mozilla_dom_CDATASection_h
diff --git a/dom/xml/ProcessingInstruction.cpp b/dom/xml/ProcessingInstruction.cpp
new file mode 100644
index 0000000000..1875487212
--- /dev/null
+++ b/dom/xml/ProcessingInstruction.cpp
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsGkAtoms.h"
+#include "nsUnicharUtils.h"
+#include "mozilla/dom/LinkStyle.h"
+#include "mozilla/dom/ProcessingInstruction.h"
+#include "mozilla/dom/ProcessingInstructionBinding.h"
+#include "mozilla/dom/XMLStylesheetProcessingInstruction.h"
+#include "mozilla/IntegerPrintfMacros.h"
+#include "nsContentUtils.h"
+
+already_AddRefed<mozilla::dom::ProcessingInstruction>
+NS_NewXMLProcessingInstruction(nsNodeInfoManager* aNodeInfoManager,
+ const nsAString& aTarget,
+ const nsAString& aData) {
+ using mozilla::dom::ProcessingInstruction;
+ using mozilla::dom::XMLStylesheetProcessingInstruction;
+
+ MOZ_ASSERT(aNodeInfoManager, "Missing nodeinfo manager");
+
+ RefPtr<nsAtom> target = NS_Atomize(aTarget);
+ MOZ_ASSERT(target);
+
+ if (target == nsGkAtoms::xml_stylesheet) {
+ RefPtr<XMLStylesheetProcessingInstruction> pi = new (aNodeInfoManager)
+ XMLStylesheetProcessingInstruction(aNodeInfoManager, aData);
+ return pi.forget();
+ }
+
+ RefPtr<mozilla::dom::NodeInfo> ni;
+ ni = aNodeInfoManager->GetNodeInfo(
+ nsGkAtoms::processingInstructionTagName, nullptr, kNameSpaceID_None,
+ nsINode::PROCESSING_INSTRUCTION_NODE, target);
+
+ RefPtr<ProcessingInstruction> instance =
+ new (aNodeInfoManager) ProcessingInstruction(ni.forget(), aData);
+
+ return instance.forget();
+}
+
+namespace mozilla::dom {
+
+ProcessingInstruction::ProcessingInstruction(
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ const nsAString& aData)
+ : CharacterData(std::move(aNodeInfo)) {
+ MOZ_ASSERT(mNodeInfo->NodeType() == nsINode::PROCESSING_INSTRUCTION_NODE,
+ "Bad NodeType in aNodeInfo");
+
+ SetTextInternal(0, mText.GetLength(), aData.BeginReading(), aData.Length(),
+ false); // Don't notify (bug 420429).
+}
+
+ProcessingInstruction::~ProcessingInstruction() = default;
+
+StyleSheet* ProcessingInstruction::GetSheetForBindings() const {
+ if (const auto* linkStyle = LinkStyle::FromNode(*this)) {
+ return linkStyle->GetSheetForBindings();
+ }
+ return nullptr;
+}
+
+JSObject* ProcessingInstruction::WrapNode(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) {
+ return ProcessingInstruction_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+bool ProcessingInstruction::GetAttrValue(nsAtom* aName, nsAString& aValue) {
+ nsAutoString data;
+
+ GetData(data);
+ return nsContentUtils::GetPseudoAttributeValue(data, aName, aValue);
+}
+
+already_AddRefed<CharacterData> ProcessingInstruction::CloneDataNode(
+ mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const {
+ nsAutoString data;
+ GetData(data);
+ RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
+ auto* nim = ni->NodeInfoManager();
+ return do_AddRef(new (nim) ProcessingInstruction(ni.forget(), data));
+}
+
+#ifdef MOZ_DOM_LIST
+void ProcessingInstruction::List(FILE* out, int32_t aIndent) const {
+ int32_t index;
+ for (index = aIndent; --index >= 0;) fputs(" ", out);
+
+ fprintf(out, "Processing instruction refcount=%" PRIuPTR "<", mRefCnt.get());
+
+ nsAutoString tmp;
+ ToCString(tmp, 0, mText.GetLength());
+ tmp.Insert(nsDependentAtomString(NodeInfo()->GetExtraName()).get(), 0);
+ fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out);
+
+ fputs(">\n", out);
+}
+
+void ProcessingInstruction::DumpContent(FILE* out, int32_t aIndent,
+ bool aDumpAll) const {}
+#endif
+
+} // namespace mozilla::dom
diff --git a/dom/xml/ProcessingInstruction.h b/dom/xml/ProcessingInstruction.h
new file mode 100644
index 0000000000..69902049d4
--- /dev/null
+++ b/dom/xml/ProcessingInstruction.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_ProcessingInstruction_h
+#define mozilla_dom_ProcessingInstruction_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/dom/CharacterData.h"
+#include "nsAString.h"
+
+class nsIPrincipal;
+class nsIURI;
+
+namespace mozilla {
+
+class StyleSheet;
+
+namespace dom {
+
+class ProcessingInstruction : public CharacterData {
+ public:
+ ProcessingInstruction(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ const nsAString& aData);
+
+ virtual already_AddRefed<CharacterData> CloneDataNode(
+ dom::NodeInfo* aNodeInfo, bool aCloneText) const override;
+
+#ifdef MOZ_DOM_LIST
+ virtual void List(FILE* out, int32_t aIndent) const override;
+ virtual void DumpContent(FILE* out, int32_t aIndent,
+ bool aDumpAll) const override;
+#endif
+
+ // WebIDL API
+ void GetTarget(nsAString& aTarget) { aTarget = NodeName(); }
+ // This is the WebIDL API for LinkStyle, even though only
+ // XMLStylesheetProcessingInstruction actually implements LinkStyle.
+ StyleSheet* GetSheetForBindings() const;
+
+ NS_IMPL_FROMNODE_HELPER(ProcessingInstruction, IsProcessingInstruction())
+
+ protected:
+ virtual ~ProcessingInstruction();
+
+ /**
+ * This will parse the content of the PI, to extract the value of the pseudo
+ * attribute with the name specified in aName. See
+ * http://www.w3.org/TR/xml-stylesheet/#NT-StyleSheetPI for the specification
+ * which is used to parse the content of the PI.
+ *
+ * @param aName the name of the attribute to get the value for
+ * @param aValue [out] the value for the attribute with name specified in
+ * aAttribute. Empty if the attribute isn't present.
+ */
+ bool GetAttrValue(nsAtom* aName, nsAString& aValue);
+
+ JSObject* WrapNode(JSContext*, JS::Handle<JSObject*> aGivenProto) override;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+/**
+ * aNodeInfoManager must not be null.
+ */
+already_AddRefed<mozilla::dom::ProcessingInstruction>
+NS_NewXMLProcessingInstruction(nsNodeInfoManager* aNodeInfoManager,
+ const nsAString& aTarget,
+ const nsAString& aData);
+
+#endif // mozilla_dom_ProcessingInstruction_h
diff --git a/dom/xml/XMLDocument.cpp b/dom/xml/XMLDocument.cpp
new file mode 100644
index 0000000000..e9c821b7d4
--- /dev/null
+++ b/dom/xml/XMLDocument.cpp
@@ -0,0 +1,338 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/XMLDocument.h"
+#include "nsCharsetSource.h"
+#include "nsIXMLContentSink.h"
+#include "nsPresContext.h"
+#include "nsIContent.h"
+#include "nsIDocShell.h"
+#include "nsHTMLParts.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsIURI.h"
+#include "nsNetUtil.h"
+#include "nsError.h"
+#include "nsIPrincipal.h"
+#include "nsLayoutCID.h"
+#include "mozilla/dom/Attr.h"
+#include "nsCExternalHandlerService.h"
+#include "nsMimeTypes.h"
+#include "nsContentUtils.h"
+#include "nsThreadUtils.h"
+#include "nsJSUtils.h"
+#include "nsCRT.h"
+#include "nsComponentManagerUtils.h"
+#include "nsContentCreatorFunctions.h"
+#include "nsContentPolicyUtils.h"
+#include "nsIConsoleService.h"
+#include "nsIScriptError.h"
+#include "nsHTMLDocument.h"
+#include "nsParser.h"
+#include "mozilla/BasicEvents.h"
+#include "mozilla/EventDispatcher.h"
+#include "mozilla/Encoding.h"
+#include "mozilla/dom/DocumentType.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/DocGroup.h"
+#include "mozilla/dom/XMLDocumentBinding.h"
+#include "mozilla/dom/DocumentBinding.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+// ==================================================================
+// =
+// ==================================================================
+
+nsresult NS_NewDOMDocument(Document** aInstancePtrResult,
+ const nsAString& aNamespaceURI,
+ const nsAString& aQualifiedName,
+ DocumentType* aDoctype, nsIURI* aDocumentURI,
+ nsIURI* aBaseURI, nsIPrincipal* aPrincipal,
+ bool aLoadedAsData, nsIGlobalObject* aEventObject,
+ DocumentFlavor aFlavor) {
+ // Note: can't require that aDocumentURI/aBaseURI/aPrincipal be non-null,
+ // since at least one caller (XMLHttpRequest) doesn't have decent args to
+ // pass in.
+
+ nsresult rv;
+
+ *aInstancePtrResult = nullptr;
+
+ nsCOMPtr<Document> d;
+ bool isHTML = false;
+ bool isXHTML = false;
+ if (aFlavor == DocumentFlavorSVG) {
+ rv = NS_NewSVGDocument(getter_AddRefs(d));
+ } else if (aFlavor == DocumentFlavorHTML) {
+ rv = NS_NewHTMLDocument(getter_AddRefs(d));
+ isHTML = true;
+ } else if (aFlavor == DocumentFlavorXML) {
+ rv = NS_NewXMLDocument(getter_AddRefs(d));
+ } else if (aFlavor == DocumentFlavorPlain) {
+ rv = NS_NewXMLDocument(getter_AddRefs(d), aLoadedAsData, true);
+ } else if (aDoctype) {
+ MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess);
+ nsAutoString publicId, name;
+ aDoctype->GetPublicId(publicId);
+ if (publicId.IsEmpty()) {
+ aDoctype->GetName(name);
+ }
+ if (name.EqualsLiteral("html") ||
+ publicId.EqualsLiteral("-//W3C//DTD HTML 4.01//EN") ||
+ publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Frameset//EN") ||
+ publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Transitional//EN") ||
+ publicId.EqualsLiteral("-//W3C//DTD HTML 4.0//EN") ||
+ publicId.EqualsLiteral("-//W3C//DTD HTML 4.0 Frameset//EN") ||
+ publicId.EqualsLiteral("-//W3C//DTD HTML 4.0 Transitional//EN")) {
+ rv = NS_NewHTMLDocument(getter_AddRefs(d));
+ isHTML = true;
+ } else if (publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Strict//EN") ||
+ publicId.EqualsLiteral(
+ "-//W3C//DTD XHTML 1.0 Transitional//EN") ||
+ publicId.EqualsLiteral("-//W3C//DTD XHTML 1.0 Frameset//EN")) {
+ rv = NS_NewHTMLDocument(getter_AddRefs(d));
+ isHTML = true;
+ isXHTML = true;
+ } else if (publicId.EqualsLiteral("-//W3C//DTD SVG 1.1//EN")) {
+ rv = NS_NewSVGDocument(getter_AddRefs(d));
+ }
+ // XXX Add support for XUL documents.
+ else {
+ rv = NS_NewXMLDocument(getter_AddRefs(d));
+ }
+ } else {
+ MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess);
+ rv = NS_NewXMLDocument(getter_AddRefs(d));
+ }
+
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ if (isHTML) {
+ d->SetCompatibilityMode(eCompatibility_FullStandards);
+ d->AsHTMLDocument()->SetIsXHTML(isXHTML);
+ }
+ d->SetLoadedAsData(aLoadedAsData, /* aConsiderForMemoryReporting */ true);
+ d->SetDocumentURI(aDocumentURI);
+ // Must set the principal first, since SetBaseURI checks it.
+ d->SetPrincipals(aPrincipal, aPrincipal);
+ d->SetBaseURI(aBaseURI);
+
+ // We need to set the script handling object after we set the principal such
+ // that the doc group is assigned correctly.
+ if (nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aEventObject)) {
+ d->SetScriptHandlingObject(sgo);
+ } else if (aEventObject) {
+ d->SetScopeObject(aEventObject);
+ }
+
+ // XMLDocuments and documents "created in memory" get to be UTF-8 by default,
+ // unlike the legacy HTML mess
+ d->SetDocumentCharacterSet(UTF_8_ENCODING);
+
+ if (aDoctype) {
+ ErrorResult result;
+ d->AppendChild(*aDoctype, result);
+ // Need to WouldReportJSException() if our callee can throw a JS
+ // exception (which it can) and we're neither propagating the
+ // error out nor unconditionally suppressing it.
+ result.WouldReportJSException();
+ if (NS_WARN_IF(result.Failed())) {
+ return result.StealNSResult();
+ }
+ }
+
+ if (!aQualifiedName.IsEmpty()) {
+ ErrorResult result;
+ ElementCreationOptionsOrString options;
+ options.SetAsString();
+
+ nsCOMPtr<Element> root =
+ d->CreateElementNS(aNamespaceURI, aQualifiedName, options, result);
+ if (NS_WARN_IF(result.Failed())) {
+ return result.StealNSResult();
+ }
+
+ d->AppendChild(*root, result);
+ // Need to WouldReportJSException() if our callee can throw a JS
+ // exception (which it can) and we're neither propagating the
+ // error out nor unconditionally suppressing it.
+ result.WouldReportJSException();
+ if (NS_WARN_IF(result.Failed())) {
+ return result.StealNSResult();
+ }
+ }
+
+ d.forget(aInstancePtrResult);
+
+ return NS_OK;
+}
+
+nsresult NS_NewXMLDocument(Document** aInstancePtrResult, bool aLoadedAsData,
+ bool aIsPlainDocument) {
+ RefPtr<XMLDocument> doc = new XMLDocument();
+
+ nsresult rv = doc->Init();
+
+ if (NS_FAILED(rv)) {
+ *aInstancePtrResult = nullptr;
+ return rv;
+ }
+
+ doc->SetLoadedAsData(aLoadedAsData, /* aConsiderForMemoryReporting */ true);
+ doc->mIsPlainDocument = aIsPlainDocument;
+ doc.forget(aInstancePtrResult);
+
+ return NS_OK;
+}
+
+namespace mozilla::dom {
+
+XMLDocument::XMLDocument(const char* aContentType)
+ : Document(aContentType),
+ mChannelIsPending(false),
+ mIsPlainDocument(false),
+ mSuppressParserErrorElement(false),
+ mSuppressParserErrorConsoleMessages(false) {
+ mType = eGenericXML;
+}
+
+nsresult XMLDocument::Init() {
+ nsresult rv = Document::Init();
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return rv;
+}
+
+void XMLDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) {
+ Document::Reset(aChannel, aLoadGroup);
+}
+
+void XMLDocument::ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup,
+ nsIPrincipal* aPrincipal,
+ nsIPrincipal* aPartitionedPrincipal) {
+ if (mChannelIsPending) {
+ StopDocumentLoad();
+ mChannel->CancelWithReason(NS_BINDING_ABORTED,
+ "XMLDocument::ResetToURI"_ns);
+ mChannelIsPending = false;
+ }
+
+ Document::ResetToURI(aURI, aLoadGroup, aPrincipal, aPartitionedPrincipal);
+}
+
+void XMLDocument::SetSuppressParserErrorElement(bool aSuppress) {
+ mSuppressParserErrorElement = aSuppress;
+}
+
+bool XMLDocument::SuppressParserErrorElement() {
+ return mSuppressParserErrorElement;
+}
+
+void XMLDocument::SetSuppressParserErrorConsoleMessages(bool aSuppress) {
+ mSuppressParserErrorConsoleMessages = aSuppress;
+}
+
+bool XMLDocument::SuppressParserErrorConsoleMessages() {
+ return mSuppressParserErrorConsoleMessages;
+}
+
+nsresult XMLDocument::StartDocumentLoad(
+ const char* aCommand, nsIChannel* aChannel, nsILoadGroup* aLoadGroup,
+ nsISupports* aContainer, nsIStreamListener** aDocListener, bool aReset) {
+ nsresult rv = Document::StartDocumentLoad(aCommand, aChannel, aLoadGroup,
+ aContainer, aDocListener, aReset);
+ if (NS_FAILED(rv)) return rv;
+
+ int32_t charsetSource = kCharsetFromDocTypeDefault;
+ NotNull<const Encoding*> encoding = UTF_8_ENCODING;
+ TryChannelCharset(aChannel, charsetSource, encoding, nullptr);
+
+ nsCOMPtr<nsIURI> aUrl;
+ rv = aChannel->GetURI(getter_AddRefs(aUrl));
+ if (NS_FAILED(rv)) return rv;
+
+ mParser = new nsParser();
+
+ nsCOMPtr<nsIXMLContentSink> sink;
+
+ nsCOMPtr<nsIDocShell> docShell;
+ if (aContainer) {
+ docShell = do_QueryInterface(aContainer);
+ NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
+ }
+ rv = NS_NewXMLContentSink(getter_AddRefs(sink), this, aUrl, docShell,
+ aChannel);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Set the parser as the stream listener for the document loader...
+ rv = CallQueryInterface(mParser, aDocListener);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_ASSERTION(mChannel, "How can we not have a channel here?");
+ mChannelIsPending = true;
+
+ SetDocumentCharacterSet(encoding);
+ mParser->SetDocumentCharset(encoding, charsetSource);
+ mParser->SetCommand(aCommand);
+ mParser->SetContentSink(sink);
+ mParser->Parse(aUrl);
+
+ return NS_OK;
+}
+
+void XMLDocument::EndLoad() {
+ mChannelIsPending = false;
+
+ mSynchronousDOMContentLoaded = mLoadedAsData;
+ Document::EndLoad();
+ if (mSynchronousDOMContentLoaded) {
+ mSynchronousDOMContentLoaded = false;
+ Document::SetReadyStateInternal(Document::READYSTATE_COMPLETE);
+ // Generate a document load event for the case when an XML
+ // document was loaded as pure data without any presentation
+ // attached to it.
+ WidgetEvent event(true, eLoad);
+ // TODO: Bug 1506441
+ EventDispatcher::Dispatch(MOZ_KnownLive(ToSupports(this)), nullptr, &event);
+ }
+}
+
+/* virtual */
+void XMLDocument::DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const {
+ Document::DocAddSizeOfExcludingThis(aWindowSizes);
+}
+
+// Document interface
+
+nsresult XMLDocument::Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const {
+ NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
+ "Can't import this document into another document!");
+
+ RefPtr<XMLDocument> clone = new XMLDocument();
+ nsresult rv = CloneDocHelper(clone);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // State from XMLDocument
+ clone->mIsPlainDocument = mIsPlainDocument;
+
+ clone.forget(aResult);
+ return NS_OK;
+}
+
+JSObject* XMLDocument::WrapNode(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) {
+ if (mIsPlainDocument) {
+ return Document_Binding::Wrap(aCx, this, aGivenProto);
+ }
+
+ return XMLDocument_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+} // namespace mozilla::dom
diff --git a/dom/xml/XMLDocument.h b/dom/xml/XMLDocument.h
new file mode 100644
index 0000000000..54ac3fb9ba
--- /dev/null
+++ b/dom/xml/XMLDocument.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_XMLDocument_h
+#define mozilla_dom_XMLDocument_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/Document.h"
+#include "nsIScriptContext.h"
+
+class nsIURI;
+class nsIChannel;
+
+namespace mozilla::dom {
+
+class XMLDocument : public Document {
+ public:
+ explicit XMLDocument(const char* aContentType = "application/xml");
+
+ NS_INLINE_DECL_REFCOUNTING_INHERITED(XMLDocument, Document)
+
+ virtual void Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) override;
+ virtual void ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup,
+ nsIPrincipal* aPrincipal,
+ nsIPrincipal* aPartitionedPrincipal) override;
+
+ virtual void SetSuppressParserErrorElement(bool aSuppress) override;
+ virtual bool SuppressParserErrorElement() override;
+
+ virtual void SetSuppressParserErrorConsoleMessages(bool aSuppress) override;
+ virtual bool SuppressParserErrorConsoleMessages() override;
+
+ virtual nsresult StartDocumentLoad(const char* aCommand, nsIChannel* channel,
+ nsILoadGroup* aLoadGroup,
+ nsISupports* aContainer,
+ nsIStreamListener** aDocListener,
+ bool aReset = true) override;
+
+ // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230, bug 1535398)
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual void EndLoad() override;
+
+ virtual nsresult Init() override;
+
+ virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
+
+ virtual void DocAddSizeOfExcludingThis(
+ nsWindowSizes& aWindowSizes) const override;
+ // DocAddSizeOfIncludingThis is inherited from Document.
+
+ // .location is [Unforgeable], so we have to make it clear that the Document
+ // version applies to us (it's shadowed by the XPCOM thing on Document).
+ using Document::GetLocation;
+
+ protected:
+ virtual ~XMLDocument() = default;
+
+ virtual JSObject* WrapNode(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) override;
+
+ friend nsresult(::NS_NewXMLDocument)(Document**, bool, bool);
+
+ // mChannelIsPending indicates whether we're currently asynchronously loading
+ // data from mChannel. It's set to true when we first find out about the
+ // channel (StartDocumentLoad) and set to false in EndLoad or if ResetToURI()
+ // is called. In the latter case our mChannel is also cancelled. Note that
+ // if this member is true, mChannel cannot be null.
+ bool mChannelIsPending;
+
+ // If true. we're really a Document, not an XMLDocument
+ bool mIsPlainDocument;
+
+ // If true, do not output <parsererror> elements. Per spec, XMLHttpRequest
+ // shouldn't output them, whereas DOMParser/others should (see bug 918703).
+ bool mSuppressParserErrorElement;
+
+ // If true, do not log parsing errors to the web console (see bug 884693).
+ bool mSuppressParserErrorConsoleMessages;
+};
+
+} // namespace mozilla::dom
+
+#endif // mozilla_dom_XMLDocument_h
diff --git a/dom/xml/XMLStylesheetProcessingInstruction.cpp b/dom/xml/XMLStylesheetProcessingInstruction.cpp
new file mode 100644
index 0000000000..9285672bbf
--- /dev/null
+++ b/dom/xml/XMLStylesheetProcessingInstruction.cpp
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "XMLStylesheetProcessingInstruction.h"
+
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/ReferrerInfo.h"
+#include "nsContentUtils.h"
+#include "nsNetUtil.h"
+
+namespace mozilla::dom {
+
+// nsISupports implementation
+
+NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(
+ XMLStylesheetProcessingInstruction, ProcessingInstruction)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(XMLStylesheetProcessingInstruction)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(
+ XMLStylesheetProcessingInstruction, ProcessingInstruction)
+ tmp->LinkStyle::Traverse(cb);
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(
+ XMLStylesheetProcessingInstruction, ProcessingInstruction)
+ tmp->LinkStyle::Unlink();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+XMLStylesheetProcessingInstruction::~XMLStylesheetProcessingInstruction() =
+ default;
+
+// nsIContent
+
+nsresult XMLStylesheetProcessingInstruction::BindToTree(BindContext& aContext,
+ nsINode& aParent) {
+ nsresult rv = ProcessingInstruction::BindToTree(aContext, aParent);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ void (XMLStylesheetProcessingInstruction::*update)() =
+ &XMLStylesheetProcessingInstruction::UpdateStyleSheetInternal;
+ nsContentUtils::AddScriptRunner(NewRunnableMethod(
+ "dom::XMLStylesheetProcessingInstruction::BindToTree", this, update));
+
+ return rv;
+}
+
+void XMLStylesheetProcessingInstruction::UnbindFromTree(bool aNullParent) {
+ nsCOMPtr<Document> oldDoc = GetUncomposedDoc();
+
+ ProcessingInstruction::UnbindFromTree(aNullParent);
+ Unused << UpdateStyleSheetInternal(oldDoc, nullptr);
+}
+
+// nsINode
+
+void XMLStylesheetProcessingInstruction::SetNodeValueInternal(
+ const nsAString& aNodeValue, ErrorResult& aError) {
+ CharacterData::SetNodeValueInternal(aNodeValue, aError);
+ if (!aError.Failed()) {
+ Unused << UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes);
+ }
+}
+
+// LinkStyle
+
+void XMLStylesheetProcessingInstruction::GetCharset(nsAString& aCharset) {
+ if (!GetAttrValue(nsGkAtoms::charset, aCharset)) {
+ aCharset.Truncate();
+ }
+}
+
+void XMLStylesheetProcessingInstruction::OverrideBaseURI(nsIURI* aNewBaseURI) {
+ mOverriddenBaseURI = aNewBaseURI;
+}
+
+Maybe<LinkStyle::SheetInfo>
+XMLStylesheetProcessingInstruction::GetStyleSheetInfo() {
+ // xml-stylesheet PI is special only in prolog
+ if (!nsContentUtils::InProlog(this)) {
+ return Nothing();
+ }
+
+ nsAutoString href;
+ if (!GetAttrValue(nsGkAtoms::href, href)) {
+ return Nothing();
+ }
+
+ nsAutoString data;
+ GetData(data);
+
+ nsAutoString title;
+ nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::title, title);
+
+ nsAutoString alternateAttr;
+ nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::alternate,
+ alternateAttr);
+
+ bool alternate = alternateAttr.EqualsLiteral("yes");
+ if (alternate && title.IsEmpty()) {
+ // alternates must have title
+ return Nothing();
+ }
+
+ nsAutoString media;
+ nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::media, media);
+
+ // Make sure the type handling here matches
+ // nsXMLContentSink::HandleProcessingInstruction
+ nsAutoString type;
+ nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type);
+
+ nsAutoString mimeType, notUsed;
+ nsContentUtils::SplitMimeType(type, mimeType, notUsed);
+ if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
+ return Nothing();
+ }
+
+ Document* doc = OwnerDoc();
+ nsIURI* baseURL =
+ mOverriddenBaseURI ? mOverriddenBaseURI.get() : doc->GetDocBaseURI();
+ auto encoding = doc->GetDocumentCharacterSet();
+ nsCOMPtr<nsIURI> uri;
+ NS_NewURI(getter_AddRefs(uri), href, encoding, baseURL);
+
+ return Some(SheetInfo{
+ *doc,
+ this,
+ uri.forget(),
+ nullptr,
+ MakeAndAddRef<ReferrerInfo>(*doc),
+ CORS_NONE,
+ title,
+ media,
+ /* integrity = */ u""_ns,
+ /* nonce = */ u""_ns,
+ alternate ? HasAlternateRel::Yes : HasAlternateRel::No,
+ IsInline::No,
+ IsExplicitlyEnabled::No,
+ });
+}
+
+already_AddRefed<CharacterData>
+XMLStylesheetProcessingInstruction::CloneDataNode(
+ mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const {
+ nsAutoString data;
+ GetData(data);
+ RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
+ auto* nim = ni->NodeInfoManager();
+ return do_AddRef(new (nim)
+ XMLStylesheetProcessingInstruction(ni.forget(), data));
+}
+
+} // namespace mozilla::dom
diff --git a/dom/xml/XMLStylesheetProcessingInstruction.h b/dom/xml/XMLStylesheetProcessingInstruction.h
new file mode 100644
index 0000000000..a6b3aa6978
--- /dev/null
+++ b/dom/xml/XMLStylesheetProcessingInstruction.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_XMLStylesheetProcessingInstruction_h
+#define mozilla_dom_XMLStylesheetProcessingInstruction_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Unused.h"
+#include "mozilla/dom/LinkStyle.h"
+#include "mozilla/dom/ProcessingInstruction.h"
+#include "nsIURI.h"
+
+namespace mozilla::dom {
+
+class XMLStylesheetProcessingInstruction final : public ProcessingInstruction,
+ public LinkStyle {
+ public:
+ XMLStylesheetProcessingInstruction(
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ const nsAString& aData)
+ : ProcessingInstruction(std::move(aNodeInfo), aData) {}
+
+ XMLStylesheetProcessingInstruction(nsNodeInfoManager* aNodeInfoManager,
+ const nsAString& aData)
+ : ProcessingInstruction(
+ aNodeInfoManager->GetNodeInfo(
+ nsGkAtoms::processingInstructionTagName, nullptr,
+ kNameSpaceID_None, PROCESSING_INSTRUCTION_NODE,
+ nsGkAtoms::xml_stylesheet),
+ aData) {}
+
+ // CC
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XMLStylesheetProcessingInstruction,
+ ProcessingInstruction)
+
+ // nsINode
+ virtual void SetNodeValueInternal(const nsAString& aNodeValue,
+ mozilla::ErrorResult& aError) override;
+
+ // nsIContent
+ virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
+ virtual void UnbindFromTree(bool aNullParent = true) override;
+
+ /**
+ * Tells this processing instruction to use a different base URI. This is used
+ * for proper loading of xml-stylesheet processing instructions in XUL
+ * overlays and is only currently used by nsXMLStylesheetPI.
+ *
+ * @param aNewBaseURI the new base URI, nullptr to use the default base URI.
+ */
+ void OverrideBaseURI(nsIURI* aNewBaseURI);
+
+ // LinkStyle
+ void GetCharset(nsAString& aCharset) override;
+
+ virtual void SetData(const nsAString& aData,
+ mozilla::ErrorResult& rv) override {
+ CharacterData::SetData(aData, rv);
+ if (rv.Failed()) {
+ return;
+ }
+ Unused << UpdateStyleSheetInternal(nullptr, nullptr, ForceUpdate::Yes);
+ }
+
+ protected:
+ virtual ~XMLStylesheetProcessingInstruction();
+
+ nsCOMPtr<nsIURI> mOverriddenBaseURI;
+
+ nsIContent& AsContent() final { return *this; }
+ const LinkStyle* AsLinkStyle() const final { return this; }
+ Maybe<SheetInfo> GetStyleSheetInfo() final;
+
+ already_AddRefed<CharacterData> CloneDataNode(
+ mozilla::dom::NodeInfo* aNodeInfo, bool aCloneText) const final;
+};
+
+} // namespace mozilla::dom
+
+#endif // mozilla_dom_XMLStylesheetProcessingInstruction_h
diff --git a/dom/xml/crashtests/1038887.xhtml b/dom/xml/crashtests/1038887.xhtml
new file mode 100644
index 0000000000..18b12083a9
--- /dev/null
+++ b/dom/xml/crashtests/1038887.xhtml
@@ -0,0 +1 @@
+<?xml-stylesheet type="text/xsl" href="http://notexistingurl"?><html xmlns="http://www.w3.org/1999/xhtml"></html>
diff --git a/dom/xml/crashtests/136896-1.xml b/dom/xml/crashtests/136896-1.xml
new file mode 100644
index 0000000000..a54f95393f
--- /dev/null
+++ b/dom/xml/crashtests/136896-1.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" standalone="yes"?>
+<!DOCTYPE SITES
+[
+ <!ELEMENT SITES (VERSION, SITE+)>
+ <!ELEMENT VERSION (#PCDATA)>
+ <!ELEMENT SITE (ID, NAME, MAXADDR, MAXALIASES, MAXQUOTA, TYPE, DOMAINS?, USERS?, ALIASES?)>
+ <!ELEMENT DOMAINS (DOMAIN*)>
+ <!ELEMENT DOMAIN (#PCDATA)>
+
+ <!ELEMENT USERS (USER*)>
+ <!ELEMENT USER (ID, NAME, ROA, ROC, QUOTA, TYPE)>
+
+ <!ELEMENT ALIASES (ALIAS*)>
+ <!ELEMENT ALIAS (LEFTPART, RIGHTPART)>
+
+ <!ELEMENT ID (#PCDATA)>
+ <!ELEMENT NAME (#PCDATA)>
+ <!ELEMENT MAXADDR (#PCDATA)>
+ <!ELEMENT MAXALIASES (#PCDATA)>
+ <!ELEMENT MAXQUOTA (#PCDATA)>
+ <!ELEMENT TYPE (#PCDATA)>
+
+ <!ELEMENT ROA (#PCDATA)>
+ <!ELEMENT ROC (#PCDATA)>
+ <!ELEMENT QUOTA (#PCDATA)>
+
+ <!ELEMENT LEFTPART (#PCDATA)>
+ <!ELEMENT RIGHTPART (#PCDATA)>
+]
+>
+<SITES>
+<VERSION>1</VERSION>
+<SITE>
+ <ID>60</ID>
+ <NAME>abtauchen</NAME>
+ <MAXADDR>1</MAXADDR>
+ <MAXALIASES>1</MAXALIASES>
+ <MAXQUOTA>10240</MAXQUOTA>
+ <TYPE>p</TYPE>
+ <DOMAINS>
+ <DOMAIN>abtauchen.at</DOMAIN>
+ <DOMAIN>abtauchen.com</DOMAIN>
+ <DOMAIN>abtauchen.net</DOMAIN>
+ </DOMAINS>
+ <USERS>
+ <USER>
+ <ID>83</ID>
+ <NAME>info</NAME>
+ <ROA>y</ROA>
+ <ROC>n</ROC>
+ <QUOTA>10240</QUOTA>
+ <TYPE>p</TYPE>
+ </USER>
+ </USERS>
+ <ALIASES>
+ <ALIAS>
+ <LEFTPART>*</LEFTPART>
+ <RIGHTPART>info</RIGHTPART>
+ </ALIAS>
+ </ALIASES>
+</SITE>
+</SITES> \ No newline at end of file
diff --git a/dom/xml/crashtests/1405878.xml b/dom/xml/crashtests/1405878.xml
new file mode 100644
index 0000000000..12677ade93
--- /dev/null
+++ b/dom/xml/crashtests/1405878.xml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <body>
+ <select>
+ <script>document.documentElement.offsetHeight</script>
+ <option>Hello there</option>
+ </select>
+ <script>
+ document.querySelector("body").style.display = "inline";
+ </script>
+ </body>
+</html>
diff --git a/dom/xml/crashtests/1523655.xml b/dom/xml/crashtests/1523655.xml
new file mode 100644
index 0000000000..e905e9104d
--- /dev/null
+++ b/dom/xml/crashtests/1523655.xml
@@ -0,0 +1,3 @@
+<body>
+ <!-- XML root element with an known, allow-to-attch-shadow-root HTML tag name in non-HTML namespace should not trigger a crash -->
+</body>
diff --git a/dom/xml/crashtests/185285-1.xml b/dom/xml/crashtests/185285-1.xml
new file mode 100644
index 0000000000..9ab44d3356
--- /dev/null
+++ b/dom/xml/crashtests/185285-1.xml
@@ -0,0 +1,2 @@
+<link xmlns="http://www.w3.org/1999/xhtml" href="some.css" rel="stylesheet" />
+<x /> \ No newline at end of file
diff --git a/dom/xml/crashtests/382636-1.xml b/dom/xml/crashtests/382636-1.xml
new file mode 100644
index 0000000000..da5110ad05
--- /dev/null
+++ b/dom/xml/crashtests/382636-1.xml
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+</head>
+<body onload="document.cloneNode(true);">
+
+<img src="tree.gif" />
+
+</body>
+</html> \ No newline at end of file
diff --git a/dom/xml/crashtests/382636-2.svg b/dom/xml/crashtests/382636-2.svg
new file mode 100644
index 0000000000..2be0060eed
--- /dev/null
+++ b/dom/xml/crashtests/382636-2.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="document.cloneNode(true);">
+
+<image xlink:href="tree.gif" width="49" height="60" />
+
+</svg>
diff --git a/dom/xml/crashtests/382636-3.xhtml b/dom/xml/crashtests/382636-3.xhtml
new file mode 100644
index 0000000000..da5110ad05
--- /dev/null
+++ b/dom/xml/crashtests/382636-3.xhtml
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+</head>
+<body onload="document.cloneNode(true);">
+
+<img src="tree.gif" />
+
+</body>
+</html> \ No newline at end of file
diff --git a/dom/xml/crashtests/382636-4.xhtml b/dom/xml/crashtests/382636-4.xhtml
new file mode 100644
index 0000000000..e1c65b9030
--- /dev/null
+++ b/dom/xml/crashtests/382636-4.xhtml
@@ -0,0 +1,5 @@
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="try { document.cloneNode(true); } catch (e) { }">
+
+<image src="tree.gif" width="49" height="60" style="-moz-box-flex: 0" />
+
+</window>
diff --git a/dom/xml/crashtests/420429.xhtml b/dom/xml/crashtests/420429.xhtml
new file mode 100644
index 0000000000..e71af4ef21
--- /dev/null
+++ b/dom/xml/crashtests/420429.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="boom();">
+
+<?xml-stylesheet?>
+
+<script type="text/javascript">
+
+function boom()
+{
+ window.addEventListener("DOMCharacterDataModified", function(){}, false);
+ document.documentElement.cloneNode(true).getElementsByTagName("*").length;
+}
+
+</script>
+
+</window>
diff --git a/dom/xml/crashtests/431703-1.xhtml b/dom/xml/crashtests/431703-1.xhtml
new file mode 100644
index 0000000000..622e4455cc
--- /dev/null
+++ b/dom/xml/crashtests/431703-1.xhtml
@@ -0,0 +1,17 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script>
+<![CDATA[
+
+function boom()
+{
+ document.body.innerHTML = '<circle xmlns="http://www.w3.org/2000/svg" onload=""/>';
+}
+
+]]>
+</script>
+</head>
+
+<body onload="boom();"></body>
+
+</html>
diff --git a/dom/xml/crashtests/453278-frame.xml b/dom/xml/crashtests/453278-frame.xml
new file mode 100644
index 0000000000..7ced674cc5
--- /dev/null
+++ b/dom/xml/crashtests/453278-frame.xml
@@ -0,0 +1,3 @@
+<xml xmlns:xlink="http://www.w3.org/1999/xlink">
+<xml xlink:href="#" xlink:actuate="onLoad" xlink:type="simple"/>
+</xml>
diff --git a/dom/xml/crashtests/453278.html b/dom/xml/crashtests/453278.html
new file mode 100644
index 0000000000..f30ea3833e
--- /dev/null
+++ b/dom/xml/crashtests/453278.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title> Bug 453278 - Crash [@ nsContentUtils::TriggerLink] with xlink stuff in display: none iframe</title><style>
+</style>
+</head>
+<body>
+<iframe id="content" src="453278-frame.xml" style="display: none;"></iframe>
+</body>
+</html>
diff --git a/dom/xml/crashtests/803586.xhtml b/dom/xml/crashtests/803586.xhtml
new file mode 100644
index 0000000000..002de07724
--- /dev/null
+++ b/dom/xml/crashtests/803586.xhtml
@@ -0,0 +1,8 @@
+<?xml-stylesheet href="foo.css" ?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script>
+document.firstChild.nodeValue = null
+</script>
+</head>
+</html>
diff --git a/dom/xml/crashtests/994740-1.xhtml b/dom/xml/crashtests/994740-1.xhtml
new file mode 100644
index 0000000000..4d71cef27f
--- /dev/null
+++ b/dom/xml/crashtests/994740-1.xhtml
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script>
+<![CDATA[
+
+function boom()
+{
+ document.createElement("head").innerHTML = "<";
+}
+
+]]>
+</script></head>
+
+<body onload="boom();"></body>
+</html>
diff --git a/dom/xml/crashtests/crashtests.list b/dom/xml/crashtests/crashtests.list
new file mode 100644
index 0000000000..158342c84d
--- /dev/null
+++ b/dom/xml/crashtests/crashtests.list
@@ -0,0 +1,14 @@
+load 136896-1.xml
+load 185285-1.xml
+load 382636-1.xml
+load 382636-2.svg
+load 382636-3.xhtml
+load chrome://reftest/content/crashtests/dom/xml/crashtests/382636-4.xhtml # Throws (bug 455856)
+load chrome://reftest/content/crashtests/dom/xml/crashtests/420429.xhtml
+load 431703-1.xhtml
+load 453278.html
+load 803586.xhtml
+load 994740-1.xhtml
+load 1038887.xhtml
+load 1405878.xml
+load 1523655.xml
diff --git a/dom/xml/crashtests/tree.gif b/dom/xml/crashtests/tree.gif
new file mode 100644
index 0000000000..360897e910
--- /dev/null
+++ b/dom/xml/crashtests/tree.gif
Binary files differ
diff --git a/dom/xml/htmlmathml-f.ent b/dom/xml/htmlmathml-f.ent
new file mode 100644
index 0000000000..37b2599769
--- /dev/null
+++ b/dom/xml/htmlmathml-f.ent
@@ -0,0 +1,2164 @@
+
+<!--
+ Copyright 1998 - 2011 W3C.
+
+ Use and distribution of this code are permitted under the terms of
+ either of the following two licences:
+
+ 1) W3C Software Notice and License.
+ http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html
+
+
+ 2) The license used for the WHATWG HTML specification,
+ which states, in full:
+ You are granted a license to use, reproduce and create derivative
+ works of this document.
+
+
+ Please report any errors to David Carlisle
+ via the public W3C list www-math@w3.org.
+
+
+ Public identifier: -//W3C//ENTITIES HTML MathML Set//EN//XML
+ System identifier: http://www.w3.org/2003/entities/2007/htmlmathml-f.ent
+
+ The public identifier should always be used verbatim.
+ The system identifier may be changed to suit local requirements.
+
+ Typical invocation:
+
+ <!ENTITY % htmlmathml-f PUBLIC
+ "-//W3C//ENTITIES HTML MathML Set//EN//XML"
+ "http://www.w3.org/2003/entities/2007/htmlmathml-f.ent"
+ >
+ %htmlmathml-f;
+
+
+
+-->
+
+<!ENTITY AElig "&#x000C6;" ><!--LATIN CAPITAL LETTER AE -->
+<!ENTITY AMP "&#38;#38;" ><!--AMPERSAND -->
+<!ENTITY Aacute "&#x000C1;" ><!--LATIN CAPITAL LETTER A WITH ACUTE -->
+<!ENTITY Abreve "&#x00102;" ><!--LATIN CAPITAL LETTER A WITH BREVE -->
+<!ENTITY Acirc "&#x000C2;" ><!--LATIN CAPITAL LETTER A WITH CIRCUMFLEX -->
+<!ENTITY Acy "&#x00410;" ><!--CYRILLIC CAPITAL LETTER A -->
+<!ENTITY Afr "&#x1D504;" ><!--MATHEMATICAL FRAKTUR CAPITAL A -->
+<!ENTITY Agrave "&#x000C0;" ><!--LATIN CAPITAL LETTER A WITH GRAVE -->
+<!ENTITY Alpha "&#x00391;" ><!--GREEK CAPITAL LETTER ALPHA -->
+<!ENTITY Amacr "&#x00100;" ><!--LATIN CAPITAL LETTER A WITH MACRON -->
+<!ENTITY And "&#x02A53;" ><!--DOUBLE LOGICAL AND -->
+<!ENTITY Aogon "&#x00104;" ><!--LATIN CAPITAL LETTER A WITH OGONEK -->
+<!ENTITY Aopf "&#x1D538;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL A -->
+<!ENTITY ApplyFunction "&#x02061;" ><!--FUNCTION APPLICATION -->
+<!ENTITY Aring "&#x000C5;" ><!--LATIN CAPITAL LETTER A WITH RING ABOVE -->
+<!ENTITY Ascr "&#x1D49C;" ><!--MATHEMATICAL SCRIPT CAPITAL A -->
+<!ENTITY Assign "&#x02254;" ><!--COLON EQUALS -->
+<!ENTITY Atilde "&#x000C3;" ><!--LATIN CAPITAL LETTER A WITH TILDE -->
+<!ENTITY Auml "&#x000C4;" ><!--LATIN CAPITAL LETTER A WITH DIAERESIS -->
+<!ENTITY Backslash "&#x02216;" ><!--SET MINUS -->
+<!ENTITY Barv "&#x02AE7;" ><!--SHORT DOWN TACK WITH OVERBAR -->
+<!ENTITY Barwed "&#x02306;" ><!--PERSPECTIVE -->
+<!ENTITY Bcy "&#x00411;" ><!--CYRILLIC CAPITAL LETTER BE -->
+<!ENTITY Because "&#x02235;" ><!--BECAUSE -->
+<!ENTITY Bernoullis "&#x0212C;" ><!--SCRIPT CAPITAL B -->
+<!ENTITY Beta "&#x00392;" ><!--GREEK CAPITAL LETTER BETA -->
+<!ENTITY Bfr "&#x1D505;" ><!--MATHEMATICAL FRAKTUR CAPITAL B -->
+<!ENTITY Bopf "&#x1D539;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL B -->
+<!ENTITY Breve "&#x002D8;" ><!--BREVE -->
+<!ENTITY Bscr "&#x0212C;" ><!--SCRIPT CAPITAL B -->
+<!ENTITY Bumpeq "&#x0224E;" ><!--GEOMETRICALLY EQUIVALENT TO -->
+<!ENTITY CHcy "&#x00427;" ><!--CYRILLIC CAPITAL LETTER CHE -->
+<!ENTITY COPY "&#x000A9;" ><!--COPYRIGHT SIGN -->
+<!ENTITY Cacute "&#x00106;" ><!--LATIN CAPITAL LETTER C WITH ACUTE -->
+<!ENTITY Cap "&#x022D2;" ><!--DOUBLE INTERSECTION -->
+<!ENTITY CapitalDifferentialD "&#x02145;" ><!--DOUBLE-STRUCK ITALIC CAPITAL D -->
+<!ENTITY Cayleys "&#x0212D;" ><!--BLACK-LETTER CAPITAL C -->
+<!ENTITY Ccaron "&#x0010C;" ><!--LATIN CAPITAL LETTER C WITH CARON -->
+<!ENTITY Ccedil "&#x000C7;" ><!--LATIN CAPITAL LETTER C WITH CEDILLA -->
+<!ENTITY Ccirc "&#x00108;" ><!--LATIN CAPITAL LETTER C WITH CIRCUMFLEX -->
+<!ENTITY Cconint "&#x02230;" ><!--VOLUME INTEGRAL -->
+<!ENTITY Cdot "&#x0010A;" ><!--LATIN CAPITAL LETTER C WITH DOT ABOVE -->
+<!ENTITY Cedilla "&#x000B8;" ><!--CEDILLA -->
+<!ENTITY CenterDot "&#x000B7;" ><!--MIDDLE DOT -->
+<!ENTITY Cfr "&#x0212D;" ><!--BLACK-LETTER CAPITAL C -->
+<!ENTITY Chi "&#x003A7;" ><!--GREEK CAPITAL LETTER CHI -->
+<!ENTITY CircleDot "&#x02299;" ><!--CIRCLED DOT OPERATOR -->
+<!ENTITY CircleMinus "&#x02296;" ><!--CIRCLED MINUS -->
+<!ENTITY CirclePlus "&#x02295;" ><!--CIRCLED PLUS -->
+<!ENTITY CircleTimes "&#x02297;" ><!--CIRCLED TIMES -->
+<!ENTITY ClockwiseContourIntegral "&#x02232;" ><!--CLOCKWISE CONTOUR INTEGRAL -->
+<!ENTITY CloseCurlyDoubleQuote "&#x0201D;" ><!--RIGHT DOUBLE QUOTATION MARK -->
+<!ENTITY CloseCurlyQuote "&#x02019;" ><!--RIGHT SINGLE QUOTATION MARK -->
+<!ENTITY Colon "&#x02237;" ><!--PROPORTION -->
+<!ENTITY Colone "&#x02A74;" ><!--DOUBLE COLON EQUAL -->
+<!ENTITY Congruent "&#x02261;" ><!--IDENTICAL TO -->
+<!ENTITY Conint "&#x0222F;" ><!--SURFACE INTEGRAL -->
+<!ENTITY ContourIntegral "&#x0222E;" ><!--CONTOUR INTEGRAL -->
+<!ENTITY Copf "&#x02102;" ><!--DOUBLE-STRUCK CAPITAL C -->
+<!ENTITY Coproduct "&#x02210;" ><!--N-ARY COPRODUCT -->
+<!ENTITY CounterClockwiseContourIntegral "&#x02233;" ><!--ANTICLOCKWISE CONTOUR INTEGRAL -->
+<!ENTITY Cross "&#x02A2F;" ><!--VECTOR OR CROSS PRODUCT -->
+<!ENTITY Cscr "&#x1D49E;" ><!--MATHEMATICAL SCRIPT CAPITAL C -->
+<!ENTITY Cup "&#x022D3;" ><!--DOUBLE UNION -->
+<!ENTITY CupCap "&#x0224D;" ><!--EQUIVALENT TO -->
+<!ENTITY DD "&#x02145;" ><!--DOUBLE-STRUCK ITALIC CAPITAL D -->
+<!ENTITY DDotrahd "&#x02911;" ><!--RIGHTWARDS ARROW WITH DOTTED STEM -->
+<!ENTITY DJcy "&#x00402;" ><!--CYRILLIC CAPITAL LETTER DJE -->
+<!ENTITY DScy "&#x00405;" ><!--CYRILLIC CAPITAL LETTER DZE -->
+<!ENTITY DZcy "&#x0040F;" ><!--CYRILLIC CAPITAL LETTER DZHE -->
+<!ENTITY Dagger "&#x02021;" ><!--DOUBLE DAGGER -->
+<!ENTITY Darr "&#x021A1;" ><!--DOWNWARDS TWO HEADED ARROW -->
+<!ENTITY Dashv "&#x02AE4;" ><!--VERTICAL BAR DOUBLE LEFT TURNSTILE -->
+<!ENTITY Dcaron "&#x0010E;" ><!--LATIN CAPITAL LETTER D WITH CARON -->
+<!ENTITY Dcy "&#x00414;" ><!--CYRILLIC CAPITAL LETTER DE -->
+<!ENTITY Del "&#x02207;" ><!--NABLA -->
+<!ENTITY Delta "&#x00394;" ><!--GREEK CAPITAL LETTER DELTA -->
+<!ENTITY Dfr "&#x1D507;" ><!--MATHEMATICAL FRAKTUR CAPITAL D -->
+<!ENTITY DiacriticalAcute "&#x000B4;" ><!--ACUTE ACCENT -->
+<!ENTITY DiacriticalDot "&#x002D9;" ><!--DOT ABOVE -->
+<!ENTITY DiacriticalDoubleAcute "&#x002DD;" ><!--DOUBLE ACUTE ACCENT -->
+<!ENTITY DiacriticalGrave "&#x00060;" ><!--GRAVE ACCENT -->
+<!ENTITY DiacriticalTilde "&#x002DC;" ><!--SMALL TILDE -->
+<!ENTITY Diamond "&#x022C4;" ><!--DIAMOND OPERATOR -->
+<!ENTITY DifferentialD "&#x02146;" ><!--DOUBLE-STRUCK ITALIC SMALL D -->
+<!ENTITY Dopf "&#x1D53B;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL D -->
+<!ENTITY Dot "&#x000A8;" ><!--DIAERESIS -->
+<!ENTITY DotDot "&#x020DC;" ><!--COMBINING FOUR DOTS ABOVE -->
+<!ENTITY DotEqual "&#x02250;" ><!--APPROACHES THE LIMIT -->
+<!ENTITY DoubleContourIntegral "&#x0222F;" ><!--SURFACE INTEGRAL -->
+<!ENTITY DoubleDot "&#x000A8;" ><!--DIAERESIS -->
+<!ENTITY DoubleDownArrow "&#x021D3;" ><!--DOWNWARDS DOUBLE ARROW -->
+<!ENTITY DoubleLeftArrow "&#x021D0;" ><!--LEFTWARDS DOUBLE ARROW -->
+<!ENTITY DoubleLeftRightArrow "&#x021D4;" ><!--LEFT RIGHT DOUBLE ARROW -->
+<!ENTITY DoubleLeftTee "&#x02AE4;" ><!--VERTICAL BAR DOUBLE LEFT TURNSTILE -->
+<!ENTITY DoubleLongLeftArrow "&#x027F8;" ><!--LONG LEFTWARDS DOUBLE ARROW -->
+<!ENTITY DoubleLongLeftRightArrow "&#x027FA;" ><!--LONG LEFT RIGHT DOUBLE ARROW -->
+<!ENTITY DoubleLongRightArrow "&#x027F9;" ><!--LONG RIGHTWARDS DOUBLE ARROW -->
+<!ENTITY DoubleRightArrow "&#x021D2;" ><!--RIGHTWARDS DOUBLE ARROW -->
+<!ENTITY DoubleRightTee "&#x022A8;" ><!--TRUE -->
+<!ENTITY DoubleUpArrow "&#x021D1;" ><!--UPWARDS DOUBLE ARROW -->
+<!ENTITY DoubleUpDownArrow "&#x021D5;" ><!--UP DOWN DOUBLE ARROW -->
+<!ENTITY DoubleVerticalBar "&#x02225;" ><!--PARALLEL TO -->
+<!ENTITY DownArrow "&#x02193;" ><!--DOWNWARDS ARROW -->
+<!ENTITY DownArrowBar "&#x02913;" ><!--DOWNWARDS ARROW TO BAR -->
+<!ENTITY DownArrowUpArrow "&#x021F5;" ><!--DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW -->
+<!ENTITY DownBreve "&#x00311;" ><!--COMBINING INVERTED BREVE -->
+<!ENTITY DownLeftRightVector "&#x02950;" ><!--LEFT BARB DOWN RIGHT BARB DOWN HARPOON -->
+<!ENTITY DownLeftTeeVector "&#x0295E;" ><!--LEFTWARDS HARPOON WITH BARB DOWN FROM BAR -->
+<!ENTITY DownLeftVector "&#x021BD;" ><!--LEFTWARDS HARPOON WITH BARB DOWNWARDS -->
+<!ENTITY DownLeftVectorBar "&#x02956;" ><!--LEFTWARDS HARPOON WITH BARB DOWN TO BAR -->
+<!ENTITY DownRightTeeVector "&#x0295F;" ><!--RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR -->
+<!ENTITY DownRightVector "&#x021C1;" ><!--RIGHTWARDS HARPOON WITH BARB DOWNWARDS -->
+<!ENTITY DownRightVectorBar "&#x02957;" ><!--RIGHTWARDS HARPOON WITH BARB DOWN TO BAR -->
+<!ENTITY DownTee "&#x022A4;" ><!--DOWN TACK -->
+<!ENTITY DownTeeArrow "&#x021A7;" ><!--DOWNWARDS ARROW FROM BAR -->
+<!ENTITY Downarrow "&#x021D3;" ><!--DOWNWARDS DOUBLE ARROW -->
+<!ENTITY Dscr "&#x1D49F;" ><!--MATHEMATICAL SCRIPT CAPITAL D -->
+<!ENTITY Dstrok "&#x00110;" ><!--LATIN CAPITAL LETTER D WITH STROKE -->
+<!ENTITY ENG "&#x0014A;" ><!--LATIN CAPITAL LETTER ENG -->
+<!ENTITY ETH "&#x000D0;" ><!--LATIN CAPITAL LETTER ETH -->
+<!ENTITY Eacute "&#x000C9;" ><!--LATIN CAPITAL LETTER E WITH ACUTE -->
+<!ENTITY Ecaron "&#x0011A;" ><!--LATIN CAPITAL LETTER E WITH CARON -->
+<!ENTITY Ecirc "&#x000CA;" ><!--LATIN CAPITAL LETTER E WITH CIRCUMFLEX -->
+<!ENTITY Ecy "&#x0042D;" ><!--CYRILLIC CAPITAL LETTER E -->
+<!ENTITY Edot "&#x00116;" ><!--LATIN CAPITAL LETTER E WITH DOT ABOVE -->
+<!ENTITY Efr "&#x1D508;" ><!--MATHEMATICAL FRAKTUR CAPITAL E -->
+<!ENTITY Egrave "&#x000C8;" ><!--LATIN CAPITAL LETTER E WITH GRAVE -->
+<!ENTITY Element "&#x02208;" ><!--ELEMENT OF -->
+<!ENTITY Emacr "&#x00112;" ><!--LATIN CAPITAL LETTER E WITH MACRON -->
+<!ENTITY EmptySmallSquare "&#x025FB;" ><!--WHITE MEDIUM SQUARE -->
+<!ENTITY EmptyVerySmallSquare "&#x025AB;" ><!--WHITE SMALL SQUARE -->
+<!ENTITY Eogon "&#x00118;" ><!--LATIN CAPITAL LETTER E WITH OGONEK -->
+<!ENTITY Eopf "&#x1D53C;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL E -->
+<!ENTITY Epsilon "&#x00395;" ><!--GREEK CAPITAL LETTER EPSILON -->
+<!ENTITY Equal "&#x02A75;" ><!--TWO CONSECUTIVE EQUALS SIGNS -->
+<!ENTITY EqualTilde "&#x02242;" ><!--MINUS TILDE -->
+<!ENTITY Equilibrium "&#x021CC;" ><!--RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON -->
+<!ENTITY Escr "&#x02130;" ><!--SCRIPT CAPITAL E -->
+<!ENTITY Esim "&#x02A73;" ><!--EQUALS SIGN ABOVE TILDE OPERATOR -->
+<!ENTITY Eta "&#x00397;" ><!--GREEK CAPITAL LETTER ETA -->
+<!ENTITY Euml "&#x000CB;" ><!--LATIN CAPITAL LETTER E WITH DIAERESIS -->
+<!ENTITY Exists "&#x02203;" ><!--THERE EXISTS -->
+<!ENTITY ExponentialE "&#x02147;" ><!--DOUBLE-STRUCK ITALIC SMALL E -->
+<!ENTITY Fcy "&#x00424;" ><!--CYRILLIC CAPITAL LETTER EF -->
+<!ENTITY Ffr "&#x1D509;" ><!--MATHEMATICAL FRAKTUR CAPITAL F -->
+<!ENTITY FilledSmallSquare "&#x025FC;" ><!--BLACK MEDIUM SQUARE -->
+<!ENTITY FilledVerySmallSquare "&#x025AA;" ><!--BLACK SMALL SQUARE -->
+<!ENTITY Fopf "&#x1D53D;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL F -->
+<!ENTITY ForAll "&#x02200;" ><!--FOR ALL -->
+<!ENTITY Fouriertrf "&#x02131;" ><!--SCRIPT CAPITAL F -->
+<!ENTITY Fscr "&#x02131;" ><!--SCRIPT CAPITAL F -->
+<!ENTITY GJcy "&#x00403;" ><!--CYRILLIC CAPITAL LETTER GJE -->
+<!ENTITY GT "&#x0003E;" ><!--GREATER-THAN SIGN -->
+<!ENTITY Gamma "&#x00393;" ><!--GREEK CAPITAL LETTER GAMMA -->
+<!ENTITY Gammad "&#x003DC;" ><!--GREEK LETTER DIGAMMA -->
+<!ENTITY Gbreve "&#x0011E;" ><!--LATIN CAPITAL LETTER G WITH BREVE -->
+<!ENTITY Gcedil "&#x00122;" ><!--LATIN CAPITAL LETTER G WITH CEDILLA -->
+<!ENTITY Gcirc "&#x0011C;" ><!--LATIN CAPITAL LETTER G WITH CIRCUMFLEX -->
+<!ENTITY Gcy "&#x00413;" ><!--CYRILLIC CAPITAL LETTER GHE -->
+<!ENTITY Gdot "&#x00120;" ><!--LATIN CAPITAL LETTER G WITH DOT ABOVE -->
+<!ENTITY Gfr "&#x1D50A;" ><!--MATHEMATICAL FRAKTUR CAPITAL G -->
+<!ENTITY Gg "&#x022D9;" ><!--VERY MUCH GREATER-THAN -->
+<!ENTITY Gopf "&#x1D53E;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL G -->
+<!ENTITY GreaterEqual "&#x02265;" ><!--GREATER-THAN OR EQUAL TO -->
+<!ENTITY GreaterEqualLess "&#x022DB;" ><!--GREATER-THAN EQUAL TO OR LESS-THAN -->
+<!ENTITY GreaterFullEqual "&#x02267;" ><!--GREATER-THAN OVER EQUAL TO -->
+<!ENTITY GreaterGreater "&#x02AA2;" ><!--DOUBLE NESTED GREATER-THAN -->
+<!ENTITY GreaterLess "&#x02277;" ><!--GREATER-THAN OR LESS-THAN -->
+<!ENTITY GreaterSlantEqual "&#x02A7E;" ><!--GREATER-THAN OR SLANTED EQUAL TO -->
+<!ENTITY GreaterTilde "&#x02273;" ><!--GREATER-THAN OR EQUIVALENT TO -->
+<!ENTITY Gscr "&#x1D4A2;" ><!--MATHEMATICAL SCRIPT CAPITAL G -->
+<!ENTITY Gt "&#x0226B;" ><!--MUCH GREATER-THAN -->
+<!ENTITY HARDcy "&#x0042A;" ><!--CYRILLIC CAPITAL LETTER HARD SIGN -->
+<!ENTITY Hacek "&#x002C7;" ><!--CARON -->
+<!ENTITY Hat "&#x0005E;" ><!--CIRCUMFLEX ACCENT -->
+<!ENTITY Hcirc "&#x00124;" ><!--LATIN CAPITAL LETTER H WITH CIRCUMFLEX -->
+<!ENTITY Hfr "&#x0210C;" ><!--BLACK-LETTER CAPITAL H -->
+<!ENTITY HilbertSpace "&#x0210B;" ><!--SCRIPT CAPITAL H -->
+<!ENTITY Hopf "&#x0210D;" ><!--DOUBLE-STRUCK CAPITAL H -->
+<!ENTITY HorizontalLine "&#x02500;" ><!--BOX DRAWINGS LIGHT HORIZONTAL -->
+<!ENTITY Hscr "&#x0210B;" ><!--SCRIPT CAPITAL H -->
+<!ENTITY Hstrok "&#x00126;" ><!--LATIN CAPITAL LETTER H WITH STROKE -->
+<!ENTITY HumpDownHump "&#x0224E;" ><!--GEOMETRICALLY EQUIVALENT TO -->
+<!ENTITY HumpEqual "&#x0224F;" ><!--DIFFERENCE BETWEEN -->
+<!ENTITY IEcy "&#x00415;" ><!--CYRILLIC CAPITAL LETTER IE -->
+<!ENTITY IJlig "&#x00132;" ><!--LATIN CAPITAL LIGATURE IJ -->
+<!ENTITY IOcy "&#x00401;" ><!--CYRILLIC CAPITAL LETTER IO -->
+<!ENTITY Iacute "&#x000CD;" ><!--LATIN CAPITAL LETTER I WITH ACUTE -->
+<!ENTITY Icirc "&#x000CE;" ><!--LATIN CAPITAL LETTER I WITH CIRCUMFLEX -->
+<!ENTITY Icy "&#x00418;" ><!--CYRILLIC CAPITAL LETTER I -->
+<!ENTITY Idot "&#x00130;" ><!--LATIN CAPITAL LETTER I WITH DOT ABOVE -->
+<!ENTITY Ifr "&#x02111;" ><!--BLACK-LETTER CAPITAL I -->
+<!ENTITY Igrave "&#x000CC;" ><!--LATIN CAPITAL LETTER I WITH GRAVE -->
+<!ENTITY Im "&#x02111;" ><!--BLACK-LETTER CAPITAL I -->
+<!ENTITY Imacr "&#x0012A;" ><!--LATIN CAPITAL LETTER I WITH MACRON -->
+<!ENTITY ImaginaryI "&#x02148;" ><!--DOUBLE-STRUCK ITALIC SMALL I -->
+<!ENTITY Implies "&#x021D2;" ><!--RIGHTWARDS DOUBLE ARROW -->
+<!ENTITY Int "&#x0222C;" ><!--DOUBLE INTEGRAL -->
+<!ENTITY Integral "&#x0222B;" ><!--INTEGRAL -->
+<!ENTITY Intersection "&#x022C2;" ><!--N-ARY INTERSECTION -->
+<!ENTITY InvisibleComma "&#x02063;" ><!--INVISIBLE SEPARATOR -->
+<!ENTITY InvisibleTimes "&#x02062;" ><!--INVISIBLE TIMES -->
+<!ENTITY Iogon "&#x0012E;" ><!--LATIN CAPITAL LETTER I WITH OGONEK -->
+<!ENTITY Iopf "&#x1D540;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL I -->
+<!ENTITY Iota "&#x00399;" ><!--GREEK CAPITAL LETTER IOTA -->
+<!ENTITY Iscr "&#x02110;" ><!--SCRIPT CAPITAL I -->
+<!ENTITY Itilde "&#x00128;" ><!--LATIN CAPITAL LETTER I WITH TILDE -->
+<!ENTITY Iukcy "&#x00406;" ><!--CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I -->
+<!ENTITY Iuml "&#x000CF;" ><!--LATIN CAPITAL LETTER I WITH DIAERESIS -->
+<!ENTITY Jcirc "&#x00134;" ><!--LATIN CAPITAL LETTER J WITH CIRCUMFLEX -->
+<!ENTITY Jcy "&#x00419;" ><!--CYRILLIC CAPITAL LETTER SHORT I -->
+<!ENTITY Jfr "&#x1D50D;" ><!--MATHEMATICAL FRAKTUR CAPITAL J -->
+<!ENTITY Jopf "&#x1D541;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL J -->
+<!ENTITY Jscr "&#x1D4A5;" ><!--MATHEMATICAL SCRIPT CAPITAL J -->
+<!ENTITY Jsercy "&#x00408;" ><!--CYRILLIC CAPITAL LETTER JE -->
+<!ENTITY Jukcy "&#x00404;" ><!--CYRILLIC CAPITAL LETTER UKRAINIAN IE -->
+<!ENTITY KHcy "&#x00425;" ><!--CYRILLIC CAPITAL LETTER HA -->
+<!ENTITY KJcy "&#x0040C;" ><!--CYRILLIC CAPITAL LETTER KJE -->
+<!ENTITY Kappa "&#x0039A;" ><!--GREEK CAPITAL LETTER KAPPA -->
+<!ENTITY Kcedil "&#x00136;" ><!--LATIN CAPITAL LETTER K WITH CEDILLA -->
+<!ENTITY Kcy "&#x0041A;" ><!--CYRILLIC CAPITAL LETTER KA -->
+<!ENTITY Kfr "&#x1D50E;" ><!--MATHEMATICAL FRAKTUR CAPITAL K -->
+<!ENTITY Kopf "&#x1D542;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL K -->
+<!ENTITY Kscr "&#x1D4A6;" ><!--MATHEMATICAL SCRIPT CAPITAL K -->
+<!ENTITY LJcy "&#x00409;" ><!--CYRILLIC CAPITAL LETTER LJE -->
+<!ENTITY LT "&#38;#60;" ><!--LESS-THAN SIGN -->
+<!ENTITY Lacute "&#x00139;" ><!--LATIN CAPITAL LETTER L WITH ACUTE -->
+<!ENTITY Lambda "&#x0039B;" ><!--GREEK CAPITAL LETTER LAMDA -->
+<!ENTITY Lang "&#x027EA;" ><!--MATHEMATICAL LEFT DOUBLE ANGLE BRACKET -->
+<!ENTITY Laplacetrf "&#x02112;" ><!--SCRIPT CAPITAL L -->
+<!ENTITY Larr "&#x0219E;" ><!--LEFTWARDS TWO HEADED ARROW -->
+<!ENTITY Lcaron "&#x0013D;" ><!--LATIN CAPITAL LETTER L WITH CARON -->
+<!ENTITY Lcedil "&#x0013B;" ><!--LATIN CAPITAL LETTER L WITH CEDILLA -->
+<!ENTITY Lcy "&#x0041B;" ><!--CYRILLIC CAPITAL LETTER EL -->
+<!ENTITY LeftAngleBracket "&#x027E8;" ><!--MATHEMATICAL LEFT ANGLE BRACKET -->
+<!ENTITY LeftArrow "&#x02190;" ><!--LEFTWARDS ARROW -->
+<!ENTITY LeftArrowBar "&#x021E4;" ><!--LEFTWARDS ARROW TO BAR -->
+<!ENTITY LeftArrowRightArrow "&#x021C6;" ><!--LEFTWARDS ARROW OVER RIGHTWARDS ARROW -->
+<!ENTITY LeftCeiling "&#x02308;" ><!--LEFT CEILING -->
+<!ENTITY LeftDoubleBracket "&#x027E6;" ><!--MATHEMATICAL LEFT WHITE SQUARE BRACKET -->
+<!ENTITY LeftDownTeeVector "&#x02961;" ><!--DOWNWARDS HARPOON WITH BARB LEFT FROM BAR -->
+<!ENTITY LeftDownVector "&#x021C3;" ><!--DOWNWARDS HARPOON WITH BARB LEFTWARDS -->
+<!ENTITY LeftDownVectorBar "&#x02959;" ><!--DOWNWARDS HARPOON WITH BARB LEFT TO BAR -->
+<!ENTITY LeftFloor "&#x0230A;" ><!--LEFT FLOOR -->
+<!ENTITY LeftRightArrow "&#x02194;" ><!--LEFT RIGHT ARROW -->
+<!ENTITY LeftRightVector "&#x0294E;" ><!--LEFT BARB UP RIGHT BARB UP HARPOON -->
+<!ENTITY LeftTee "&#x022A3;" ><!--LEFT TACK -->
+<!ENTITY LeftTeeArrow "&#x021A4;" ><!--LEFTWARDS ARROW FROM BAR -->
+<!ENTITY LeftTeeVector "&#x0295A;" ><!--LEFTWARDS HARPOON WITH BARB UP FROM BAR -->
+<!ENTITY LeftTriangle "&#x022B2;" ><!--NORMAL SUBGROUP OF -->
+<!ENTITY LeftTriangleBar "&#x029CF;" ><!--LEFT TRIANGLE BESIDE VERTICAL BAR -->
+<!ENTITY LeftTriangleEqual "&#x022B4;" ><!--NORMAL SUBGROUP OF OR EQUAL TO -->
+<!ENTITY LeftUpDownVector "&#x02951;" ><!--UP BARB LEFT DOWN BARB LEFT HARPOON -->
+<!ENTITY LeftUpTeeVector "&#x02960;" ><!--UPWARDS HARPOON WITH BARB LEFT FROM BAR -->
+<!ENTITY LeftUpVector "&#x021BF;" ><!--UPWARDS HARPOON WITH BARB LEFTWARDS -->
+<!ENTITY LeftUpVectorBar "&#x02958;" ><!--UPWARDS HARPOON WITH BARB LEFT TO BAR -->
+<!ENTITY LeftVector "&#x021BC;" ><!--LEFTWARDS HARPOON WITH BARB UPWARDS -->
+<!ENTITY LeftVectorBar "&#x02952;" ><!--LEFTWARDS HARPOON WITH BARB UP TO BAR -->
+<!ENTITY Leftarrow "&#x021D0;" ><!--LEFTWARDS DOUBLE ARROW -->
+<!ENTITY Leftrightarrow "&#x021D4;" ><!--LEFT RIGHT DOUBLE ARROW -->
+<!ENTITY LessEqualGreater "&#x022DA;" ><!--LESS-THAN EQUAL TO OR GREATER-THAN -->
+<!ENTITY LessFullEqual "&#x02266;" ><!--LESS-THAN OVER EQUAL TO -->
+<!ENTITY LessGreater "&#x02276;" ><!--LESS-THAN OR GREATER-THAN -->
+<!ENTITY LessLess "&#x02AA1;" ><!--DOUBLE NESTED LESS-THAN -->
+<!ENTITY LessSlantEqual "&#x02A7D;" ><!--LESS-THAN OR SLANTED EQUAL TO -->
+<!ENTITY LessTilde "&#x02272;" ><!--LESS-THAN OR EQUIVALENT TO -->
+<!ENTITY Lfr "&#x1D50F;" ><!--MATHEMATICAL FRAKTUR CAPITAL L -->
+<!ENTITY Ll "&#x022D8;" ><!--VERY MUCH LESS-THAN -->
+<!ENTITY Lleftarrow "&#x021DA;" ><!--LEFTWARDS TRIPLE ARROW -->
+<!ENTITY Lmidot "&#x0013F;" ><!--LATIN CAPITAL LETTER L WITH MIDDLE DOT -->
+<!ENTITY LongLeftArrow "&#x027F5;" ><!--LONG LEFTWARDS ARROW -->
+<!ENTITY LongLeftRightArrow "&#x027F7;" ><!--LONG LEFT RIGHT ARROW -->
+<!ENTITY LongRightArrow "&#x027F6;" ><!--LONG RIGHTWARDS ARROW -->
+<!ENTITY Longleftarrow "&#x027F8;" ><!--LONG LEFTWARDS DOUBLE ARROW -->
+<!ENTITY Longleftrightarrow "&#x027FA;" ><!--LONG LEFT RIGHT DOUBLE ARROW -->
+<!ENTITY Longrightarrow "&#x027F9;" ><!--LONG RIGHTWARDS DOUBLE ARROW -->
+<!ENTITY Lopf "&#x1D543;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL L -->
+<!ENTITY LowerLeftArrow "&#x02199;" ><!--SOUTH WEST ARROW -->
+<!ENTITY LowerRightArrow "&#x02198;" ><!--SOUTH EAST ARROW -->
+<!ENTITY Lscr "&#x02112;" ><!--SCRIPT CAPITAL L -->
+<!ENTITY Lsh "&#x021B0;" ><!--UPWARDS ARROW WITH TIP LEFTWARDS -->
+<!ENTITY Lstrok "&#x00141;" ><!--LATIN CAPITAL LETTER L WITH STROKE -->
+<!ENTITY Lt "&#x0226A;" ><!--MUCH LESS-THAN -->
+<!ENTITY Map "&#x02905;" ><!--RIGHTWARDS TWO-HEADED ARROW FROM BAR -->
+<!ENTITY Mcy "&#x0041C;" ><!--CYRILLIC CAPITAL LETTER EM -->
+<!ENTITY MediumSpace "&#x0205F;" ><!--MEDIUM MATHEMATICAL SPACE -->
+<!ENTITY Mellintrf "&#x02133;" ><!--SCRIPT CAPITAL M -->
+<!ENTITY Mfr "&#x1D510;" ><!--MATHEMATICAL FRAKTUR CAPITAL M -->
+<!ENTITY MinusPlus "&#x02213;" ><!--MINUS-OR-PLUS SIGN -->
+<!ENTITY Mopf "&#x1D544;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL M -->
+<!ENTITY Mscr "&#x02133;" ><!--SCRIPT CAPITAL M -->
+<!ENTITY Mu "&#x0039C;" ><!--GREEK CAPITAL LETTER MU -->
+<!ENTITY NJcy "&#x0040A;" ><!--CYRILLIC CAPITAL LETTER NJE -->
+<!ENTITY Nacute "&#x00143;" ><!--LATIN CAPITAL LETTER N WITH ACUTE -->
+<!ENTITY Ncaron "&#x00147;" ><!--LATIN CAPITAL LETTER N WITH CARON -->
+<!ENTITY Ncedil "&#x00145;" ><!--LATIN CAPITAL LETTER N WITH CEDILLA -->
+<!ENTITY Ncy "&#x0041D;" ><!--CYRILLIC CAPITAL LETTER EN -->
+<!ENTITY NegativeMediumSpace "&#x0200B;" ><!--ZERO WIDTH SPACE -->
+<!ENTITY NegativeThickSpace "&#x0200B;" ><!--ZERO WIDTH SPACE -->
+<!ENTITY NegativeThinSpace "&#x0200B;" ><!--ZERO WIDTH SPACE -->
+<!ENTITY NegativeVeryThinSpace "&#x0200B;" ><!--ZERO WIDTH SPACE -->
+<!ENTITY NestedGreaterGreater "&#x0226B;" ><!--MUCH GREATER-THAN -->
+<!ENTITY NestedLessLess "&#x0226A;" ><!--MUCH LESS-THAN -->
+<!ENTITY NewLine "&#x0000A;" ><!--LINE FEED (LF) -->
+<!ENTITY Nfr "&#x1D511;" ><!--MATHEMATICAL FRAKTUR CAPITAL N -->
+<!ENTITY NoBreak "&#x02060;" ><!--WORD JOINER -->
+<!ENTITY NonBreakingSpace "&#x000A0;" ><!--NO-BREAK SPACE -->
+<!ENTITY Nopf "&#x02115;" ><!--DOUBLE-STRUCK CAPITAL N -->
+<!ENTITY Not "&#x02AEC;" ><!--DOUBLE STROKE NOT SIGN -->
+<!ENTITY NotCongruent "&#x02262;" ><!--NOT IDENTICAL TO -->
+<!ENTITY NotCupCap "&#x0226D;" ><!--NOT EQUIVALENT TO -->
+<!ENTITY NotDoubleVerticalBar "&#x02226;" ><!--NOT PARALLEL TO -->
+<!ENTITY NotElement "&#x02209;" ><!--NOT AN ELEMENT OF -->
+<!ENTITY NotEqual "&#x02260;" ><!--NOT EQUAL TO -->
+<!ENTITY NotEqualTilde "&#x02242;&#x00338;" ><!--MINUS TILDE with slash -->
+<!ENTITY NotExists "&#x02204;" ><!--THERE DOES NOT EXIST -->
+<!ENTITY NotGreater "&#x0226F;" ><!--NOT GREATER-THAN -->
+<!ENTITY NotGreaterEqual "&#x02271;" ><!--NEITHER GREATER-THAN NOR EQUAL TO -->
+<!ENTITY NotGreaterFullEqual "&#x02267;&#x00338;" ><!--GREATER-THAN OVER EQUAL TO with slash -->
+<!ENTITY NotGreaterGreater "&#x0226B;&#x00338;" ><!--MUCH GREATER THAN with slash -->
+<!ENTITY NotGreaterLess "&#x02279;" ><!--NEITHER GREATER-THAN NOR LESS-THAN -->
+<!ENTITY NotGreaterSlantEqual "&#x02A7E;&#x00338;" ><!--GREATER-THAN OR SLANTED EQUAL TO with slash -->
+<!ENTITY NotGreaterTilde "&#x02275;" ><!--NEITHER GREATER-THAN NOR EQUIVALENT TO -->
+<!ENTITY NotHumpDownHump "&#x0224E;&#x00338;" ><!--GEOMETRICALLY EQUIVALENT TO with slash -->
+<!ENTITY NotHumpEqual "&#x0224F;&#x00338;" ><!--DIFFERENCE BETWEEN with slash -->
+<!ENTITY NotLeftTriangle "&#x022EA;" ><!--NOT NORMAL SUBGROUP OF -->
+<!ENTITY NotLeftTriangleBar "&#x029CF;&#x00338;" ><!--LEFT TRIANGLE BESIDE VERTICAL BAR with slash -->
+<!ENTITY NotLeftTriangleEqual "&#x022EC;" ><!--NOT NORMAL SUBGROUP OF OR EQUAL TO -->
+<!ENTITY NotLess "&#x0226E;" ><!--NOT LESS-THAN -->
+<!ENTITY NotLessEqual "&#x02270;" ><!--NEITHER LESS-THAN NOR EQUAL TO -->
+<!ENTITY NotLessGreater "&#x02278;" ><!--NEITHER LESS-THAN NOR GREATER-THAN -->
+<!ENTITY NotLessLess "&#x0226A;&#x00338;" ><!--MUCH LESS THAN with slash -->
+<!ENTITY NotLessSlantEqual "&#x02A7D;&#x00338;" ><!--LESS-THAN OR SLANTED EQUAL TO with slash -->
+<!ENTITY NotLessTilde "&#x02274;" ><!--NEITHER LESS-THAN NOR EQUIVALENT TO -->
+<!ENTITY NotNestedGreaterGreater "&#x02AA2;&#x00338;" ><!--DOUBLE NESTED GREATER-THAN with slash -->
+<!ENTITY NotNestedLessLess "&#x02AA1;&#x00338;" ><!--DOUBLE NESTED LESS-THAN with slash -->
+<!ENTITY NotPrecedes "&#x02280;" ><!--DOES NOT PRECEDE -->
+<!ENTITY NotPrecedesEqual "&#x02AAF;&#x00338;" ><!--PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash -->
+<!ENTITY NotPrecedesSlantEqual "&#x022E0;" ><!--DOES NOT PRECEDE OR EQUAL -->
+<!ENTITY NotReverseElement "&#x0220C;" ><!--DOES NOT CONTAIN AS MEMBER -->
+<!ENTITY NotRightTriangle "&#x022EB;" ><!--DOES NOT CONTAIN AS NORMAL SUBGROUP -->
+<!ENTITY NotRightTriangleBar "&#x029D0;&#x00338;" ><!--VERTICAL BAR BESIDE RIGHT TRIANGLE with slash -->
+<!ENTITY NotRightTriangleEqual "&#x022ED;" ><!--DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL -->
+<!ENTITY NotSquareSubset "&#x0228F;&#x00338;" ><!--SQUARE IMAGE OF with slash -->
+<!ENTITY NotSquareSubsetEqual "&#x022E2;" ><!--NOT SQUARE IMAGE OF OR EQUAL TO -->
+<!ENTITY NotSquareSuperset "&#x02290;&#x00338;" ><!--SQUARE ORIGINAL OF with slash -->
+<!ENTITY NotSquareSupersetEqual "&#x022E3;" ><!--NOT SQUARE ORIGINAL OF OR EQUAL TO -->
+<!ENTITY NotSubset "&#x02282;&#x020D2;" ><!--SUBSET OF with vertical line -->
+<!ENTITY NotSubsetEqual "&#x02288;" ><!--NEITHER A SUBSET OF NOR EQUAL TO -->
+<!ENTITY NotSucceeds "&#x02281;" ><!--DOES NOT SUCCEED -->
+<!ENTITY NotSucceedsEqual "&#x02AB0;&#x00338;" ><!--SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash -->
+<!ENTITY NotSucceedsSlantEqual "&#x022E1;" ><!--DOES NOT SUCCEED OR EQUAL -->
+<!ENTITY NotSucceedsTilde "&#x0227F;&#x00338;" ><!--SUCCEEDS OR EQUIVALENT TO with slash -->
+<!ENTITY NotSuperset "&#x02283;&#x020D2;" ><!--SUPERSET OF with vertical line -->
+<!ENTITY NotSupersetEqual "&#x02289;" ><!--NEITHER A SUPERSET OF NOR EQUAL TO -->
+<!ENTITY NotTilde "&#x02241;" ><!--NOT TILDE -->
+<!ENTITY NotTildeEqual "&#x02244;" ><!--NOT ASYMPTOTICALLY EQUAL TO -->
+<!ENTITY NotTildeFullEqual "&#x02247;" ><!--NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO -->
+<!ENTITY NotTildeTilde "&#x02249;" ><!--NOT ALMOST EQUAL TO -->
+<!ENTITY NotVerticalBar "&#x02224;" ><!--DOES NOT DIVIDE -->
+<!ENTITY Nscr "&#x1D4A9;" ><!--MATHEMATICAL SCRIPT CAPITAL N -->
+<!ENTITY Ntilde "&#x000D1;" ><!--LATIN CAPITAL LETTER N WITH TILDE -->
+<!ENTITY Nu "&#x0039D;" ><!--GREEK CAPITAL LETTER NU -->
+<!ENTITY OElig "&#x00152;" ><!--LATIN CAPITAL LIGATURE OE -->
+<!ENTITY Oacute "&#x000D3;" ><!--LATIN CAPITAL LETTER O WITH ACUTE -->
+<!ENTITY Ocirc "&#x000D4;" ><!--LATIN CAPITAL LETTER O WITH CIRCUMFLEX -->
+<!ENTITY Ocy "&#x0041E;" ><!--CYRILLIC CAPITAL LETTER O -->
+<!ENTITY Odblac "&#x00150;" ><!--LATIN CAPITAL LETTER O WITH DOUBLE ACUTE -->
+<!ENTITY Ofr "&#x1D512;" ><!--MATHEMATICAL FRAKTUR CAPITAL O -->
+<!ENTITY Ograve "&#x000D2;" ><!--LATIN CAPITAL LETTER O WITH GRAVE -->
+<!ENTITY Omacr "&#x0014C;" ><!--LATIN CAPITAL LETTER O WITH MACRON -->
+<!ENTITY Omega "&#x003A9;" ><!--GREEK CAPITAL LETTER OMEGA -->
+<!ENTITY Omicron "&#x0039F;" ><!--GREEK CAPITAL LETTER OMICRON -->
+<!ENTITY Oopf "&#x1D546;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL O -->
+<!ENTITY OpenCurlyDoubleQuote "&#x0201C;" ><!--LEFT DOUBLE QUOTATION MARK -->
+<!ENTITY OpenCurlyQuote "&#x02018;" ><!--LEFT SINGLE QUOTATION MARK -->
+<!ENTITY Or "&#x02A54;" ><!--DOUBLE LOGICAL OR -->
+<!ENTITY Oscr "&#x1D4AA;" ><!--MATHEMATICAL SCRIPT CAPITAL O -->
+<!ENTITY Oslash "&#x000D8;" ><!--LATIN CAPITAL LETTER O WITH STROKE -->
+<!ENTITY Otilde "&#x000D5;" ><!--LATIN CAPITAL LETTER O WITH TILDE -->
+<!ENTITY Otimes "&#x02A37;" ><!--MULTIPLICATION SIGN IN DOUBLE CIRCLE -->
+<!ENTITY Ouml "&#x000D6;" ><!--LATIN CAPITAL LETTER O WITH DIAERESIS -->
+<!ENTITY OverBar "&#x0203E;" ><!--OVERLINE -->
+<!ENTITY OverBrace "&#x023DE;" ><!--TOP CURLY BRACKET -->
+<!ENTITY OverBracket "&#x023B4;" ><!--TOP SQUARE BRACKET -->
+<!ENTITY OverParenthesis "&#x023DC;" ><!--TOP PARENTHESIS -->
+<!ENTITY PartialD "&#x02202;" ><!--PARTIAL DIFFERENTIAL -->
+<!ENTITY Pcy "&#x0041F;" ><!--CYRILLIC CAPITAL LETTER PE -->
+<!ENTITY Pfr "&#x1D513;" ><!--MATHEMATICAL FRAKTUR CAPITAL P -->
+<!ENTITY Phi "&#x003A6;" ><!--GREEK CAPITAL LETTER PHI -->
+<!ENTITY Pi "&#x003A0;" ><!--GREEK CAPITAL LETTER PI -->
+<!ENTITY PlusMinus "&#x000B1;" ><!--PLUS-MINUS SIGN -->
+<!ENTITY Poincareplane "&#x0210C;" ><!--BLACK-LETTER CAPITAL H -->
+<!ENTITY Popf "&#x02119;" ><!--DOUBLE-STRUCK CAPITAL P -->
+<!ENTITY Pr "&#x02ABB;" ><!--DOUBLE PRECEDES -->
+<!ENTITY Precedes "&#x0227A;" ><!--PRECEDES -->
+<!ENTITY PrecedesEqual "&#x02AAF;" ><!--PRECEDES ABOVE SINGLE-LINE EQUALS SIGN -->
+<!ENTITY PrecedesSlantEqual "&#x0227C;" ><!--PRECEDES OR EQUAL TO -->
+<!ENTITY PrecedesTilde "&#x0227E;" ><!--PRECEDES OR EQUIVALENT TO -->
+<!ENTITY Prime "&#x02033;" ><!--DOUBLE PRIME -->
+<!ENTITY Product "&#x0220F;" ><!--N-ARY PRODUCT -->
+<!ENTITY Proportion "&#x02237;" ><!--PROPORTION -->
+<!ENTITY Proportional "&#x0221D;" ><!--PROPORTIONAL TO -->
+<!ENTITY Pscr "&#x1D4AB;" ><!--MATHEMATICAL SCRIPT CAPITAL P -->
+<!ENTITY Psi "&#x003A8;" ><!--GREEK CAPITAL LETTER PSI -->
+<!ENTITY QUOT "&#x00022;" ><!--QUOTATION MARK -->
+<!ENTITY Qfr "&#x1D514;" ><!--MATHEMATICAL FRAKTUR CAPITAL Q -->
+<!ENTITY Qopf "&#x0211A;" ><!--DOUBLE-STRUCK CAPITAL Q -->
+<!ENTITY Qscr "&#x1D4AC;" ><!--MATHEMATICAL SCRIPT CAPITAL Q -->
+<!ENTITY RBarr "&#x02910;" ><!--RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW -->
+<!ENTITY REG "&#x000AE;" ><!--REGISTERED SIGN -->
+<!ENTITY Racute "&#x00154;" ><!--LATIN CAPITAL LETTER R WITH ACUTE -->
+<!ENTITY Rang "&#x027EB;" ><!--MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET -->
+<!ENTITY Rarr "&#x021A0;" ><!--RIGHTWARDS TWO HEADED ARROW -->
+<!ENTITY Rarrtl "&#x02916;" ><!--RIGHTWARDS TWO-HEADED ARROW WITH TAIL -->
+<!ENTITY Rcaron "&#x00158;" ><!--LATIN CAPITAL LETTER R WITH CARON -->
+<!ENTITY Rcedil "&#x00156;" ><!--LATIN CAPITAL LETTER R WITH CEDILLA -->
+<!ENTITY Rcy "&#x00420;" ><!--CYRILLIC CAPITAL LETTER ER -->
+<!ENTITY Re "&#x0211C;" ><!--BLACK-LETTER CAPITAL R -->
+<!ENTITY ReverseElement "&#x0220B;" ><!--CONTAINS AS MEMBER -->
+<!ENTITY ReverseEquilibrium "&#x021CB;" ><!--LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON -->
+<!ENTITY ReverseUpEquilibrium "&#x0296F;" ><!--DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT -->
+<!ENTITY Rfr "&#x0211C;" ><!--BLACK-LETTER CAPITAL R -->
+<!ENTITY Rho "&#x003A1;" ><!--GREEK CAPITAL LETTER RHO -->
+<!ENTITY RightAngleBracket "&#x027E9;" ><!--MATHEMATICAL RIGHT ANGLE BRACKET -->
+<!ENTITY RightArrow "&#x02192;" ><!--RIGHTWARDS ARROW -->
+<!ENTITY RightArrowBar "&#x021E5;" ><!--RIGHTWARDS ARROW TO BAR -->
+<!ENTITY RightArrowLeftArrow "&#x021C4;" ><!--RIGHTWARDS ARROW OVER LEFTWARDS ARROW -->
+<!ENTITY RightCeiling "&#x02309;" ><!--RIGHT CEILING -->
+<!ENTITY RightDoubleBracket "&#x027E7;" ><!--MATHEMATICAL RIGHT WHITE SQUARE BRACKET -->
+<!ENTITY RightDownTeeVector "&#x0295D;" ><!--DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR -->
+<!ENTITY RightDownVector "&#x021C2;" ><!--DOWNWARDS HARPOON WITH BARB RIGHTWARDS -->
+<!ENTITY RightDownVectorBar "&#x02955;" ><!--DOWNWARDS HARPOON WITH BARB RIGHT TO BAR -->
+<!ENTITY RightFloor "&#x0230B;" ><!--RIGHT FLOOR -->
+<!ENTITY RightTee "&#x022A2;" ><!--RIGHT TACK -->
+<!ENTITY RightTeeArrow "&#x021A6;" ><!--RIGHTWARDS ARROW FROM BAR -->
+<!ENTITY RightTeeVector "&#x0295B;" ><!--RIGHTWARDS HARPOON WITH BARB UP FROM BAR -->
+<!ENTITY RightTriangle "&#x022B3;" ><!--CONTAINS AS NORMAL SUBGROUP -->
+<!ENTITY RightTriangleBar "&#x029D0;" ><!--VERTICAL BAR BESIDE RIGHT TRIANGLE -->
+<!ENTITY RightTriangleEqual "&#x022B5;" ><!--CONTAINS AS NORMAL SUBGROUP OR EQUAL TO -->
+<!ENTITY RightUpDownVector "&#x0294F;" ><!--UP BARB RIGHT DOWN BARB RIGHT HARPOON -->
+<!ENTITY RightUpTeeVector "&#x0295C;" ><!--UPWARDS HARPOON WITH BARB RIGHT FROM BAR -->
+<!ENTITY RightUpVector "&#x021BE;" ><!--UPWARDS HARPOON WITH BARB RIGHTWARDS -->
+<!ENTITY RightUpVectorBar "&#x02954;" ><!--UPWARDS HARPOON WITH BARB RIGHT TO BAR -->
+<!ENTITY RightVector "&#x021C0;" ><!--RIGHTWARDS HARPOON WITH BARB UPWARDS -->
+<!ENTITY RightVectorBar "&#x02953;" ><!--RIGHTWARDS HARPOON WITH BARB UP TO BAR -->
+<!ENTITY Rightarrow "&#x021D2;" ><!--RIGHTWARDS DOUBLE ARROW -->
+<!ENTITY Ropf "&#x0211D;" ><!--DOUBLE-STRUCK CAPITAL R -->
+<!ENTITY RoundImplies "&#x02970;" ><!--RIGHT DOUBLE ARROW WITH ROUNDED HEAD -->
+<!ENTITY Rrightarrow "&#x021DB;" ><!--RIGHTWARDS TRIPLE ARROW -->
+<!ENTITY Rscr "&#x0211B;" ><!--SCRIPT CAPITAL R -->
+<!ENTITY Rsh "&#x021B1;" ><!--UPWARDS ARROW WITH TIP RIGHTWARDS -->
+<!ENTITY RuleDelayed "&#x029F4;" ><!--RULE-DELAYED -->
+<!ENTITY SHCHcy "&#x00429;" ><!--CYRILLIC CAPITAL LETTER SHCHA -->
+<!ENTITY SHcy "&#x00428;" ><!--CYRILLIC CAPITAL LETTER SHA -->
+<!ENTITY SOFTcy "&#x0042C;" ><!--CYRILLIC CAPITAL LETTER SOFT SIGN -->
+<!ENTITY Sacute "&#x0015A;" ><!--LATIN CAPITAL LETTER S WITH ACUTE -->
+<!ENTITY Sc "&#x02ABC;" ><!--DOUBLE SUCCEEDS -->
+<!ENTITY Scaron "&#x00160;" ><!--LATIN CAPITAL LETTER S WITH CARON -->
+<!ENTITY Scedil "&#x0015E;" ><!--LATIN CAPITAL LETTER S WITH CEDILLA -->
+<!ENTITY Scirc "&#x0015C;" ><!--LATIN CAPITAL LETTER S WITH CIRCUMFLEX -->
+<!ENTITY Scy "&#x00421;" ><!--CYRILLIC CAPITAL LETTER ES -->
+<!ENTITY Sfr "&#x1D516;" ><!--MATHEMATICAL FRAKTUR CAPITAL S -->
+<!ENTITY ShortDownArrow "&#x02193;" ><!--DOWNWARDS ARROW -->
+<!ENTITY ShortLeftArrow "&#x02190;" ><!--LEFTWARDS ARROW -->
+<!ENTITY ShortRightArrow "&#x02192;" ><!--RIGHTWARDS ARROW -->
+<!ENTITY ShortUpArrow "&#x02191;" ><!--UPWARDS ARROW -->
+<!ENTITY Sigma "&#x003A3;" ><!--GREEK CAPITAL LETTER SIGMA -->
+<!ENTITY SmallCircle "&#x02218;" ><!--RING OPERATOR -->
+<!ENTITY Sopf "&#x1D54A;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL S -->
+<!ENTITY Sqrt "&#x0221A;" ><!--SQUARE ROOT -->
+<!ENTITY Square "&#x025A1;" ><!--WHITE SQUARE -->
+<!ENTITY SquareIntersection "&#x02293;" ><!--SQUARE CAP -->
+<!ENTITY SquareSubset "&#x0228F;" ><!--SQUARE IMAGE OF -->
+<!ENTITY SquareSubsetEqual "&#x02291;" ><!--SQUARE IMAGE OF OR EQUAL TO -->
+<!ENTITY SquareSuperset "&#x02290;" ><!--SQUARE ORIGINAL OF -->
+<!ENTITY SquareSupersetEqual "&#x02292;" ><!--SQUARE ORIGINAL OF OR EQUAL TO -->
+<!ENTITY SquareUnion "&#x02294;" ><!--SQUARE CUP -->
+<!ENTITY Sscr "&#x1D4AE;" ><!--MATHEMATICAL SCRIPT CAPITAL S -->
+<!ENTITY Star "&#x022C6;" ><!--STAR OPERATOR -->
+<!ENTITY Sub "&#x022D0;" ><!--DOUBLE SUBSET -->
+<!ENTITY Subset "&#x022D0;" ><!--DOUBLE SUBSET -->
+<!ENTITY SubsetEqual "&#x02286;" ><!--SUBSET OF OR EQUAL TO -->
+<!ENTITY Succeeds "&#x0227B;" ><!--SUCCEEDS -->
+<!ENTITY SucceedsEqual "&#x02AB0;" ><!--SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN -->
+<!ENTITY SucceedsSlantEqual "&#x0227D;" ><!--SUCCEEDS OR EQUAL TO -->
+<!ENTITY SucceedsTilde "&#x0227F;" ><!--SUCCEEDS OR EQUIVALENT TO -->
+<!ENTITY SuchThat "&#x0220B;" ><!--CONTAINS AS MEMBER -->
+<!ENTITY Sum "&#x02211;" ><!--N-ARY SUMMATION -->
+<!ENTITY Sup "&#x022D1;" ><!--DOUBLE SUPERSET -->
+<!ENTITY Superset "&#x02283;" ><!--SUPERSET OF -->
+<!ENTITY SupersetEqual "&#x02287;" ><!--SUPERSET OF OR EQUAL TO -->
+<!ENTITY Supset "&#x022D1;" ><!--DOUBLE SUPERSET -->
+<!ENTITY THORN "&#x000DE;" ><!--LATIN CAPITAL LETTER THORN -->
+<!ENTITY TRADE "&#x02122;" ><!--TRADE MARK SIGN -->
+<!ENTITY TSHcy "&#x0040B;" ><!--CYRILLIC CAPITAL LETTER TSHE -->
+<!ENTITY TScy "&#x00426;" ><!--CYRILLIC CAPITAL LETTER TSE -->
+<!ENTITY Tab "&#x00009;" ><!--CHARACTER TABULATION -->
+<!ENTITY Tau "&#x003A4;" ><!--GREEK CAPITAL LETTER TAU -->
+<!ENTITY Tcaron "&#x00164;" ><!--LATIN CAPITAL LETTER T WITH CARON -->
+<!ENTITY Tcedil "&#x00162;" ><!--LATIN CAPITAL LETTER T WITH CEDILLA -->
+<!ENTITY Tcy "&#x00422;" ><!--CYRILLIC CAPITAL LETTER TE -->
+<!ENTITY Tfr "&#x1D517;" ><!--MATHEMATICAL FRAKTUR CAPITAL T -->
+<!ENTITY Therefore "&#x02234;" ><!--THEREFORE -->
+<!ENTITY Theta "&#x00398;" ><!--GREEK CAPITAL LETTER THETA -->
+<!ENTITY ThickSpace "&#x0205F;&#x0200A;" ><!--space of width 5/18 em -->
+<!ENTITY ThinSpace "&#x02009;" ><!--THIN SPACE -->
+<!ENTITY Tilde "&#x0223C;" ><!--TILDE OPERATOR -->
+<!ENTITY TildeEqual "&#x02243;" ><!--ASYMPTOTICALLY EQUAL TO -->
+<!ENTITY TildeFullEqual "&#x02245;" ><!--APPROXIMATELY EQUAL TO -->
+<!ENTITY TildeTilde "&#x02248;" ><!--ALMOST EQUAL TO -->
+<!ENTITY Topf "&#x1D54B;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL T -->
+<!ENTITY TripleDot "&#x020DB;" ><!--COMBINING THREE DOTS ABOVE -->
+<!ENTITY Tscr "&#x1D4AF;" ><!--MATHEMATICAL SCRIPT CAPITAL T -->
+<!ENTITY Tstrok "&#x00166;" ><!--LATIN CAPITAL LETTER T WITH STROKE -->
+<!ENTITY Uacute "&#x000DA;" ><!--LATIN CAPITAL LETTER U WITH ACUTE -->
+<!ENTITY Uarr "&#x0219F;" ><!--UPWARDS TWO HEADED ARROW -->
+<!ENTITY Uarrocir "&#x02949;" ><!--UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE -->
+<!ENTITY Ubrcy "&#x0040E;" ><!--CYRILLIC CAPITAL LETTER SHORT U -->
+<!ENTITY Ubreve "&#x0016C;" ><!--LATIN CAPITAL LETTER U WITH BREVE -->
+<!ENTITY Ucirc "&#x000DB;" ><!--LATIN CAPITAL LETTER U WITH CIRCUMFLEX -->
+<!ENTITY Ucy "&#x00423;" ><!--CYRILLIC CAPITAL LETTER U -->
+<!ENTITY Udblac "&#x00170;" ><!--LATIN CAPITAL LETTER U WITH DOUBLE ACUTE -->
+<!ENTITY Ufr "&#x1D518;" ><!--MATHEMATICAL FRAKTUR CAPITAL U -->
+<!ENTITY Ugrave "&#x000D9;" ><!--LATIN CAPITAL LETTER U WITH GRAVE -->
+<!ENTITY Umacr "&#x0016A;" ><!--LATIN CAPITAL LETTER U WITH MACRON -->
+<!ENTITY UnderBar "&#x0005F;" ><!--LOW LINE -->
+<!ENTITY UnderBrace "&#x023DF;" ><!--BOTTOM CURLY BRACKET -->
+<!ENTITY UnderBracket "&#x023B5;" ><!--BOTTOM SQUARE BRACKET -->
+<!ENTITY UnderParenthesis "&#x023DD;" ><!--BOTTOM PARENTHESIS -->
+<!ENTITY Union "&#x022C3;" ><!--N-ARY UNION -->
+<!ENTITY UnionPlus "&#x0228E;" ><!--MULTISET UNION -->
+<!ENTITY Uogon "&#x00172;" ><!--LATIN CAPITAL LETTER U WITH OGONEK -->
+<!ENTITY Uopf "&#x1D54C;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL U -->
+<!ENTITY UpArrow "&#x02191;" ><!--UPWARDS ARROW -->
+<!ENTITY UpArrowBar "&#x02912;" ><!--UPWARDS ARROW TO BAR -->
+<!ENTITY UpArrowDownArrow "&#x021C5;" ><!--UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW -->
+<!ENTITY UpDownArrow "&#x02195;" ><!--UP DOWN ARROW -->
+<!ENTITY UpEquilibrium "&#x0296E;" ><!--UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT -->
+<!ENTITY UpTee "&#x022A5;" ><!--UP TACK -->
+<!ENTITY UpTeeArrow "&#x021A5;" ><!--UPWARDS ARROW FROM BAR -->
+<!ENTITY Uparrow "&#x021D1;" ><!--UPWARDS DOUBLE ARROW -->
+<!ENTITY Updownarrow "&#x021D5;" ><!--UP DOWN DOUBLE ARROW -->
+<!ENTITY UpperLeftArrow "&#x02196;" ><!--NORTH WEST ARROW -->
+<!ENTITY UpperRightArrow "&#x02197;" ><!--NORTH EAST ARROW -->
+<!ENTITY Upsi "&#x003D2;" ><!--GREEK UPSILON WITH HOOK SYMBOL -->
+<!ENTITY Upsilon "&#x003A5;" ><!--GREEK CAPITAL LETTER UPSILON -->
+<!ENTITY Uring "&#x0016E;" ><!--LATIN CAPITAL LETTER U WITH RING ABOVE -->
+<!ENTITY Uscr "&#x1D4B0;" ><!--MATHEMATICAL SCRIPT CAPITAL U -->
+<!ENTITY Utilde "&#x00168;" ><!--LATIN CAPITAL LETTER U WITH TILDE -->
+<!ENTITY Uuml "&#x000DC;" ><!--LATIN CAPITAL LETTER U WITH DIAERESIS -->
+<!ENTITY VDash "&#x022AB;" ><!--DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE -->
+<!ENTITY Vbar "&#x02AEB;" ><!--DOUBLE UP TACK -->
+<!ENTITY Vcy "&#x00412;" ><!--CYRILLIC CAPITAL LETTER VE -->
+<!ENTITY Vdash "&#x022A9;" ><!--FORCES -->
+<!ENTITY Vdashl "&#x02AE6;" ><!--LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL -->
+<!ENTITY Vee "&#x022C1;" ><!--N-ARY LOGICAL OR -->
+<!ENTITY Verbar "&#x02016;" ><!--DOUBLE VERTICAL LINE -->
+<!ENTITY Vert "&#x02016;" ><!--DOUBLE VERTICAL LINE -->
+<!ENTITY VerticalBar "&#x02223;" ><!--DIVIDES -->
+<!ENTITY VerticalLine "&#x0007C;" ><!--VERTICAL LINE -->
+<!ENTITY VerticalSeparator "&#x02758;" ><!--LIGHT VERTICAL BAR -->
+<!ENTITY VerticalTilde "&#x02240;" ><!--WREATH PRODUCT -->
+<!ENTITY VeryThinSpace "&#x0200A;" ><!--HAIR SPACE -->
+<!ENTITY Vfr "&#x1D519;" ><!--MATHEMATICAL FRAKTUR CAPITAL V -->
+<!ENTITY Vopf "&#x1D54D;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL V -->
+<!ENTITY Vscr "&#x1D4B1;" ><!--MATHEMATICAL SCRIPT CAPITAL V -->
+<!ENTITY Vvdash "&#x022AA;" ><!--TRIPLE VERTICAL BAR RIGHT TURNSTILE -->
+<!ENTITY Wcirc "&#x00174;" ><!--LATIN CAPITAL LETTER W WITH CIRCUMFLEX -->
+<!ENTITY Wedge "&#x022C0;" ><!--N-ARY LOGICAL AND -->
+<!ENTITY Wfr "&#x1D51A;" ><!--MATHEMATICAL FRAKTUR CAPITAL W -->
+<!ENTITY Wopf "&#x1D54E;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL W -->
+<!ENTITY Wscr "&#x1D4B2;" ><!--MATHEMATICAL SCRIPT CAPITAL W -->
+<!ENTITY Xfr "&#x1D51B;" ><!--MATHEMATICAL FRAKTUR CAPITAL X -->
+<!ENTITY Xi "&#x0039E;" ><!--GREEK CAPITAL LETTER XI -->
+<!ENTITY Xopf "&#x1D54F;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL X -->
+<!ENTITY Xscr "&#x1D4B3;" ><!--MATHEMATICAL SCRIPT CAPITAL X -->
+<!ENTITY YAcy "&#x0042F;" ><!--CYRILLIC CAPITAL LETTER YA -->
+<!ENTITY YIcy "&#x00407;" ><!--CYRILLIC CAPITAL LETTER YI -->
+<!ENTITY YUcy "&#x0042E;" ><!--CYRILLIC CAPITAL LETTER YU -->
+<!ENTITY Yacute "&#x000DD;" ><!--LATIN CAPITAL LETTER Y WITH ACUTE -->
+<!ENTITY Ycirc "&#x00176;" ><!--LATIN CAPITAL LETTER Y WITH CIRCUMFLEX -->
+<!ENTITY Ycy "&#x0042B;" ><!--CYRILLIC CAPITAL LETTER YERU -->
+<!ENTITY Yfr "&#x1D51C;" ><!--MATHEMATICAL FRAKTUR CAPITAL Y -->
+<!ENTITY Yopf "&#x1D550;" ><!--MATHEMATICAL DOUBLE-STRUCK CAPITAL Y -->
+<!ENTITY Yscr "&#x1D4B4;" ><!--MATHEMATICAL SCRIPT CAPITAL Y -->
+<!ENTITY Yuml "&#x00178;" ><!--LATIN CAPITAL LETTER Y WITH DIAERESIS -->
+<!ENTITY ZHcy "&#x00416;" ><!--CYRILLIC CAPITAL LETTER ZHE -->
+<!ENTITY Zacute "&#x00179;" ><!--LATIN CAPITAL LETTER Z WITH ACUTE -->
+<!ENTITY Zcaron "&#x0017D;" ><!--LATIN CAPITAL LETTER Z WITH CARON -->
+<!ENTITY Zcy "&#x00417;" ><!--CYRILLIC CAPITAL LETTER ZE -->
+<!ENTITY Zdot "&#x0017B;" ><!--LATIN CAPITAL LETTER Z WITH DOT ABOVE -->
+<!ENTITY ZeroWidthSpace "&#x0200B;" ><!--ZERO WIDTH SPACE -->
+<!ENTITY Zeta "&#x00396;" ><!--GREEK CAPITAL LETTER ZETA -->
+<!ENTITY Zfr "&#x02128;" ><!--BLACK-LETTER CAPITAL Z -->
+<!ENTITY Zopf "&#x02124;" ><!--DOUBLE-STRUCK CAPITAL Z -->
+<!ENTITY Zscr "&#x1D4B5;" ><!--MATHEMATICAL SCRIPT CAPITAL Z -->
+<!ENTITY aacute "&#x000E1;" ><!--LATIN SMALL LETTER A WITH ACUTE -->
+<!ENTITY abreve "&#x00103;" ><!--LATIN SMALL LETTER A WITH BREVE -->
+<!ENTITY ac "&#x0223E;" ><!--INVERTED LAZY S -->
+<!ENTITY acE "&#x0223E;&#x00333;" ><!--INVERTED LAZY S with double underline -->
+<!ENTITY acd "&#x0223F;" ><!--SINE WAVE -->
+<!ENTITY acirc "&#x000E2;" ><!--LATIN SMALL LETTER A WITH CIRCUMFLEX -->
+<!ENTITY acute "&#x000B4;" ><!--ACUTE ACCENT -->
+<!ENTITY acy "&#x00430;" ><!--CYRILLIC SMALL LETTER A -->
+<!ENTITY aelig "&#x000E6;" ><!--LATIN SMALL LETTER AE -->
+<!ENTITY af "&#x02061;" ><!--FUNCTION APPLICATION -->
+<!ENTITY afr "&#x1D51E;" ><!--MATHEMATICAL FRAKTUR SMALL A -->
+<!ENTITY agrave "&#x000E0;" ><!--LATIN SMALL LETTER A WITH GRAVE -->
+<!ENTITY alefsym "&#x02135;" ><!--ALEF SYMBOL -->
+<!ENTITY aleph "&#x02135;" ><!--ALEF SYMBOL -->
+<!ENTITY alpha "&#x003B1;" ><!--GREEK SMALL LETTER ALPHA -->
+<!ENTITY amacr "&#x00101;" ><!--LATIN SMALL LETTER A WITH MACRON -->
+<!ENTITY amalg "&#x02A3F;" ><!--AMALGAMATION OR COPRODUCT -->
+<!ENTITY amp "&#38;#38;" ><!--AMPERSAND -->
+<!ENTITY and "&#x02227;" ><!--LOGICAL AND -->
+<!ENTITY andand "&#x02A55;" ><!--TWO INTERSECTING LOGICAL AND -->
+<!ENTITY andd "&#x02A5C;" ><!--LOGICAL AND WITH HORIZONTAL DASH -->
+<!ENTITY andslope "&#x02A58;" ><!--SLOPING LARGE AND -->
+<!ENTITY andv "&#x02A5A;" ><!--LOGICAL AND WITH MIDDLE STEM -->
+<!ENTITY ang "&#x02220;" ><!--ANGLE -->
+<!ENTITY ange "&#x029A4;" ><!--ANGLE WITH UNDERBAR -->
+<!ENTITY angle "&#x02220;" ><!--ANGLE -->
+<!ENTITY angmsd "&#x02221;" ><!--MEASURED ANGLE -->
+<!ENTITY angmsdaa "&#x029A8;" ><!--MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT -->
+<!ENTITY angmsdab "&#x029A9;" ><!--MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT -->
+<!ENTITY angmsdac "&#x029AA;" ><!--MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT -->
+<!ENTITY angmsdad "&#x029AB;" ><!--MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT -->
+<!ENTITY angmsdae "&#x029AC;" ><!--MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP -->
+<!ENTITY angmsdaf "&#x029AD;" ><!--MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP -->
+<!ENTITY angmsdag "&#x029AE;" ><!--MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN -->
+<!ENTITY angmsdah "&#x029AF;" ><!--MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN -->
+<!ENTITY angrt "&#x0221F;" ><!--RIGHT ANGLE -->
+<!ENTITY angrtvb "&#x022BE;" ><!--RIGHT ANGLE WITH ARC -->
+<!ENTITY angrtvbd "&#x0299D;" ><!--MEASURED RIGHT ANGLE WITH DOT -->
+<!ENTITY angsph "&#x02222;" ><!--SPHERICAL ANGLE -->
+<!ENTITY angst "&#x000C5;" ><!--LATIN CAPITAL LETTER A WITH RING ABOVE -->
+<!ENTITY angzarr "&#x0237C;" ><!--RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW -->
+<!ENTITY aogon "&#x00105;" ><!--LATIN SMALL LETTER A WITH OGONEK -->
+<!ENTITY aopf "&#x1D552;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL A -->
+<!ENTITY ap "&#x02248;" ><!--ALMOST EQUAL TO -->
+<!ENTITY apE "&#x02A70;" ><!--APPROXIMATELY EQUAL OR EQUAL TO -->
+<!ENTITY apacir "&#x02A6F;" ><!--ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT -->
+<!ENTITY ape "&#x0224A;" ><!--ALMOST EQUAL OR EQUAL TO -->
+<!ENTITY apid "&#x0224B;" ><!--TRIPLE TILDE -->
+<!ENTITY apos "&#x00027;" ><!--APOSTROPHE -->
+<!ENTITY approx "&#x02248;" ><!--ALMOST EQUAL TO -->
+<!ENTITY approxeq "&#x0224A;" ><!--ALMOST EQUAL OR EQUAL TO -->
+<!ENTITY aring "&#x000E5;" ><!--LATIN SMALL LETTER A WITH RING ABOVE -->
+<!ENTITY ascr "&#x1D4B6;" ><!--MATHEMATICAL SCRIPT SMALL A -->
+<!ENTITY ast "&#x0002A;" ><!--ASTERISK -->
+<!ENTITY asymp "&#x02248;" ><!--ALMOST EQUAL TO -->
+<!ENTITY asympeq "&#x0224D;" ><!--EQUIVALENT TO -->
+<!ENTITY atilde "&#x000E3;" ><!--LATIN SMALL LETTER A WITH TILDE -->
+<!ENTITY auml "&#x000E4;" ><!--LATIN SMALL LETTER A WITH DIAERESIS -->
+<!ENTITY awconint "&#x02233;" ><!--ANTICLOCKWISE CONTOUR INTEGRAL -->
+<!ENTITY awint "&#x02A11;" ><!--ANTICLOCKWISE INTEGRATION -->
+<!ENTITY bNot "&#x02AED;" ><!--REVERSED DOUBLE STROKE NOT SIGN -->
+<!ENTITY backcong "&#x0224C;" ><!--ALL EQUAL TO -->
+<!ENTITY backepsilon "&#x003F6;" ><!--GREEK REVERSED LUNATE EPSILON SYMBOL -->
+<!ENTITY backprime "&#x02035;" ><!--REVERSED PRIME -->
+<!ENTITY backsim "&#x0223D;" ><!--REVERSED TILDE -->
+<!ENTITY backsimeq "&#x022CD;" ><!--REVERSED TILDE EQUALS -->
+<!ENTITY barvee "&#x022BD;" ><!--NOR -->
+<!ENTITY barwed "&#x02305;" ><!--PROJECTIVE -->
+<!ENTITY barwedge "&#x02305;" ><!--PROJECTIVE -->
+<!ENTITY bbrk "&#x023B5;" ><!--BOTTOM SQUARE BRACKET -->
+<!ENTITY bbrktbrk "&#x023B6;" ><!--BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET -->
+<!ENTITY bcong "&#x0224C;" ><!--ALL EQUAL TO -->
+<!ENTITY bcy "&#x00431;" ><!--CYRILLIC SMALL LETTER BE -->
+<!ENTITY bdquo "&#x0201E;" ><!--DOUBLE LOW-9 QUOTATION MARK -->
+<!ENTITY becaus "&#x02235;" ><!--BECAUSE -->
+<!ENTITY because "&#x02235;" ><!--BECAUSE -->
+<!ENTITY bemptyv "&#x029B0;" ><!--REVERSED EMPTY SET -->
+<!ENTITY bepsi "&#x003F6;" ><!--GREEK REVERSED LUNATE EPSILON SYMBOL -->
+<!ENTITY bernou "&#x0212C;" ><!--SCRIPT CAPITAL B -->
+<!ENTITY beta "&#x003B2;" ><!--GREEK SMALL LETTER BETA -->
+<!ENTITY beth "&#x02136;" ><!--BET SYMBOL -->
+<!ENTITY between "&#x0226C;" ><!--BETWEEN -->
+<!ENTITY bfr "&#x1D51F;" ><!--MATHEMATICAL FRAKTUR SMALL B -->
+<!ENTITY bigcap "&#x022C2;" ><!--N-ARY INTERSECTION -->
+<!ENTITY bigcirc "&#x025EF;" ><!--LARGE CIRCLE -->
+<!ENTITY bigcup "&#x022C3;" ><!--N-ARY UNION -->
+<!ENTITY bigodot "&#x02A00;" ><!--N-ARY CIRCLED DOT OPERATOR -->
+<!ENTITY bigoplus "&#x02A01;" ><!--N-ARY CIRCLED PLUS OPERATOR -->
+<!ENTITY bigotimes "&#x02A02;" ><!--N-ARY CIRCLED TIMES OPERATOR -->
+<!ENTITY bigsqcup "&#x02A06;" ><!--N-ARY SQUARE UNION OPERATOR -->
+<!ENTITY bigstar "&#x02605;" ><!--BLACK STAR -->
+<!ENTITY bigtriangledown "&#x025BD;" ><!--WHITE DOWN-POINTING TRIANGLE -->
+<!ENTITY bigtriangleup "&#x025B3;" ><!--WHITE UP-POINTING TRIANGLE -->
+<!ENTITY biguplus "&#x02A04;" ><!--N-ARY UNION OPERATOR WITH PLUS -->
+<!ENTITY bigvee "&#x022C1;" ><!--N-ARY LOGICAL OR -->
+<!ENTITY bigwedge "&#x022C0;" ><!--N-ARY LOGICAL AND -->
+<!ENTITY bkarow "&#x0290D;" ><!--RIGHTWARDS DOUBLE DASH ARROW -->
+<!ENTITY blacklozenge "&#x029EB;" ><!--BLACK LOZENGE -->
+<!ENTITY blacksquare "&#x025AA;" ><!--BLACK SMALL SQUARE -->
+<!ENTITY blacktriangle "&#x025B4;" ><!--BLACK UP-POINTING SMALL TRIANGLE -->
+<!ENTITY blacktriangledown "&#x025BE;" ><!--BLACK DOWN-POINTING SMALL TRIANGLE -->
+<!ENTITY blacktriangleleft "&#x025C2;" ><!--BLACK LEFT-POINTING SMALL TRIANGLE -->
+<!ENTITY blacktriangleright "&#x025B8;" ><!--BLACK RIGHT-POINTING SMALL TRIANGLE -->
+<!ENTITY blank "&#x02423;" ><!--OPEN BOX -->
+<!ENTITY blk12 "&#x02592;" ><!--MEDIUM SHADE -->
+<!ENTITY blk14 "&#x02591;" ><!--LIGHT SHADE -->
+<!ENTITY blk34 "&#x02593;" ><!--DARK SHADE -->
+<!ENTITY block "&#x02588;" ><!--FULL BLOCK -->
+<!ENTITY bne "&#x0003D;&#x020E5;" ><!--EQUALS SIGN with reverse slash -->
+<!ENTITY bnequiv "&#x02261;&#x020E5;" ><!--IDENTICAL TO with reverse slash -->
+<!ENTITY bnot "&#x02310;" ><!--REVERSED NOT SIGN -->
+<!ENTITY bopf "&#x1D553;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL B -->
+<!ENTITY bot "&#x022A5;" ><!--UP TACK -->
+<!ENTITY bottom "&#x022A5;" ><!--UP TACK -->
+<!ENTITY bowtie "&#x022C8;" ><!--BOWTIE -->
+<!ENTITY boxDL "&#x02557;" ><!--BOX DRAWINGS DOUBLE DOWN AND LEFT -->
+<!ENTITY boxDR "&#x02554;" ><!--BOX DRAWINGS DOUBLE DOWN AND RIGHT -->
+<!ENTITY boxDl "&#x02556;" ><!--BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE -->
+<!ENTITY boxDr "&#x02553;" ><!--BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE -->
+<!ENTITY boxH "&#x02550;" ><!--BOX DRAWINGS DOUBLE HORIZONTAL -->
+<!ENTITY boxHD "&#x02566;" ><!--BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL -->
+<!ENTITY boxHU "&#x02569;" ><!--BOX DRAWINGS DOUBLE UP AND HORIZONTAL -->
+<!ENTITY boxHd "&#x02564;" ><!--BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE -->
+<!ENTITY boxHu "&#x02567;" ><!--BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE -->
+<!ENTITY boxUL "&#x0255D;" ><!--BOX DRAWINGS DOUBLE UP AND LEFT -->
+<!ENTITY boxUR "&#x0255A;" ><!--BOX DRAWINGS DOUBLE UP AND RIGHT -->
+<!ENTITY boxUl "&#x0255C;" ><!--BOX DRAWINGS UP DOUBLE AND LEFT SINGLE -->
+<!ENTITY boxUr "&#x02559;" ><!--BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE -->
+<!ENTITY boxV "&#x02551;" ><!--BOX DRAWINGS DOUBLE VERTICAL -->
+<!ENTITY boxVH "&#x0256C;" ><!--BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL -->
+<!ENTITY boxVL "&#x02563;" ><!--BOX DRAWINGS DOUBLE VERTICAL AND LEFT -->
+<!ENTITY boxVR "&#x02560;" ><!--BOX DRAWINGS DOUBLE VERTICAL AND RIGHT -->
+<!ENTITY boxVh "&#x0256B;" ><!--BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE -->
+<!ENTITY boxVl "&#x02562;" ><!--BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE -->
+<!ENTITY boxVr "&#x0255F;" ><!--BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE -->
+<!ENTITY boxbox "&#x029C9;" ><!--TWO JOINED SQUARES -->
+<!ENTITY boxdL "&#x02555;" ><!--BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE -->
+<!ENTITY boxdR "&#x02552;" ><!--BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE -->
+<!ENTITY boxdl "&#x02510;" ><!--BOX DRAWINGS LIGHT DOWN AND LEFT -->
+<!ENTITY boxdr "&#x0250C;" ><!--BOX DRAWINGS LIGHT DOWN AND RIGHT -->
+<!ENTITY boxh "&#x02500;" ><!--BOX DRAWINGS LIGHT HORIZONTAL -->
+<!ENTITY boxhD "&#x02565;" ><!--BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE -->
+<!ENTITY boxhU "&#x02568;" ><!--BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE -->
+<!ENTITY boxhd "&#x0252C;" ><!--BOX DRAWINGS LIGHT DOWN AND HORIZONTAL -->
+<!ENTITY boxhu "&#x02534;" ><!--BOX DRAWINGS LIGHT UP AND HORIZONTAL -->
+<!ENTITY boxminus "&#x0229F;" ><!--SQUARED MINUS -->
+<!ENTITY boxplus "&#x0229E;" ><!--SQUARED PLUS -->
+<!ENTITY boxtimes "&#x022A0;" ><!--SQUARED TIMES -->
+<!ENTITY boxuL "&#x0255B;" ><!--BOX DRAWINGS UP SINGLE AND LEFT DOUBLE -->
+<!ENTITY boxuR "&#x02558;" ><!--BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE -->
+<!ENTITY boxul "&#x02518;" ><!--BOX DRAWINGS LIGHT UP AND LEFT -->
+<!ENTITY boxur "&#x02514;" ><!--BOX DRAWINGS LIGHT UP AND RIGHT -->
+<!ENTITY boxv "&#x02502;" ><!--BOX DRAWINGS LIGHT VERTICAL -->
+<!ENTITY boxvH "&#x0256A;" ><!--BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE -->
+<!ENTITY boxvL "&#x02561;" ><!--BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE -->
+<!ENTITY boxvR "&#x0255E;" ><!--BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE -->
+<!ENTITY boxvh "&#x0253C;" ><!--BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL -->
+<!ENTITY boxvl "&#x02524;" ><!--BOX DRAWINGS LIGHT VERTICAL AND LEFT -->
+<!ENTITY boxvr "&#x0251C;" ><!--BOX DRAWINGS LIGHT VERTICAL AND RIGHT -->
+<!ENTITY bprime "&#x02035;" ><!--REVERSED PRIME -->
+<!ENTITY breve "&#x002D8;" ><!--BREVE -->
+<!ENTITY brvbar "&#x000A6;" ><!--BROKEN BAR -->
+<!ENTITY bscr "&#x1D4B7;" ><!--MATHEMATICAL SCRIPT SMALL B -->
+<!ENTITY bsemi "&#x0204F;" ><!--REVERSED SEMICOLON -->
+<!ENTITY bsim "&#x0223D;" ><!--REVERSED TILDE -->
+<!ENTITY bsime "&#x022CD;" ><!--REVERSED TILDE EQUALS -->
+<!ENTITY bsol "&#x0005C;" ><!--REVERSE SOLIDUS -->
+<!ENTITY bsolb "&#x029C5;" ><!--SQUARED FALLING DIAGONAL SLASH -->
+<!ENTITY bsolhsub "&#x027C8;" ><!--REVERSE SOLIDUS PRECEDING SUBSET -->
+<!ENTITY bull "&#x02022;" ><!--BULLET -->
+<!ENTITY bullet "&#x02022;" ><!--BULLET -->
+<!ENTITY bump "&#x0224E;" ><!--GEOMETRICALLY EQUIVALENT TO -->
+<!ENTITY bumpE "&#x02AAE;" ><!--EQUALS SIGN WITH BUMPY ABOVE -->
+<!ENTITY bumpe "&#x0224F;" ><!--DIFFERENCE BETWEEN -->
+<!ENTITY bumpeq "&#x0224F;" ><!--DIFFERENCE BETWEEN -->
+<!ENTITY cacute "&#x00107;" ><!--LATIN SMALL LETTER C WITH ACUTE -->
+<!ENTITY cap "&#x02229;" ><!--INTERSECTION -->
+<!ENTITY capand "&#x02A44;" ><!--INTERSECTION WITH LOGICAL AND -->
+<!ENTITY capbrcup "&#x02A49;" ><!--INTERSECTION ABOVE BAR ABOVE UNION -->
+<!ENTITY capcap "&#x02A4B;" ><!--INTERSECTION BESIDE AND JOINED WITH INTERSECTION -->
+<!ENTITY capcup "&#x02A47;" ><!--INTERSECTION ABOVE UNION -->
+<!ENTITY capdot "&#x02A40;" ><!--INTERSECTION WITH DOT -->
+<!ENTITY caps "&#x02229;&#x0FE00;" ><!--INTERSECTION with serifs -->
+<!ENTITY caret "&#x02041;" ><!--CARET INSERTION POINT -->
+<!ENTITY caron "&#x002C7;" ><!--CARON -->
+<!ENTITY ccaps "&#x02A4D;" ><!--CLOSED INTERSECTION WITH SERIFS -->
+<!ENTITY ccaron "&#x0010D;" ><!--LATIN SMALL LETTER C WITH CARON -->
+<!ENTITY ccedil "&#x000E7;" ><!--LATIN SMALL LETTER C WITH CEDILLA -->
+<!ENTITY ccirc "&#x00109;" ><!--LATIN SMALL LETTER C WITH CIRCUMFLEX -->
+<!ENTITY ccups "&#x02A4C;" ><!--CLOSED UNION WITH SERIFS -->
+<!ENTITY ccupssm "&#x02A50;" ><!--CLOSED UNION WITH SERIFS AND SMASH PRODUCT -->
+<!ENTITY cdot "&#x0010B;" ><!--LATIN SMALL LETTER C WITH DOT ABOVE -->
+<!ENTITY cedil "&#x000B8;" ><!--CEDILLA -->
+<!ENTITY cemptyv "&#x029B2;" ><!--EMPTY SET WITH SMALL CIRCLE ABOVE -->
+<!ENTITY cent "&#x000A2;" ><!--CENT SIGN -->
+<!ENTITY centerdot "&#x000B7;" ><!--MIDDLE DOT -->
+<!ENTITY cfr "&#x1D520;" ><!--MATHEMATICAL FRAKTUR SMALL C -->
+<!ENTITY chcy "&#x00447;" ><!--CYRILLIC SMALL LETTER CHE -->
+<!ENTITY check "&#x02713;" ><!--CHECK MARK -->
+<!ENTITY checkmark "&#x02713;" ><!--CHECK MARK -->
+<!ENTITY chi "&#x003C7;" ><!--GREEK SMALL LETTER CHI -->
+<!ENTITY cir "&#x025CB;" ><!--WHITE CIRCLE -->
+<!ENTITY cirE "&#x029C3;" ><!--CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT -->
+<!ENTITY circ "&#x002C6;" ><!--MODIFIER LETTER CIRCUMFLEX ACCENT -->
+<!ENTITY circeq "&#x02257;" ><!--RING EQUAL TO -->
+<!ENTITY circlearrowleft "&#x021BA;" ><!--ANTICLOCKWISE OPEN CIRCLE ARROW -->
+<!ENTITY circlearrowright "&#x021BB;" ><!--CLOCKWISE OPEN CIRCLE ARROW -->
+<!ENTITY circledR "&#x000AE;" ><!--REGISTERED SIGN -->
+<!ENTITY circledS "&#x024C8;" ><!--CIRCLED LATIN CAPITAL LETTER S -->
+<!ENTITY circledast "&#x0229B;" ><!--CIRCLED ASTERISK OPERATOR -->
+<!ENTITY circledcirc "&#x0229A;" ><!--CIRCLED RING OPERATOR -->
+<!ENTITY circleddash "&#x0229D;" ><!--CIRCLED DASH -->
+<!ENTITY cire "&#x02257;" ><!--RING EQUAL TO -->
+<!ENTITY cirfnint "&#x02A10;" ><!--CIRCULATION FUNCTION -->
+<!ENTITY cirmid "&#x02AEF;" ><!--VERTICAL LINE WITH CIRCLE ABOVE -->
+<!ENTITY cirscir "&#x029C2;" ><!--CIRCLE WITH SMALL CIRCLE TO THE RIGHT -->
+<!ENTITY clubs "&#x02663;" ><!--BLACK CLUB SUIT -->
+<!ENTITY clubsuit "&#x02663;" ><!--BLACK CLUB SUIT -->
+<!ENTITY colon "&#x0003A;" ><!--COLON -->
+<!ENTITY colone "&#x02254;" ><!--COLON EQUALS -->
+<!ENTITY coloneq "&#x02254;" ><!--COLON EQUALS -->
+<!ENTITY comma "&#x0002C;" ><!--COMMA -->
+<!ENTITY commat "&#x00040;" ><!--COMMERCIAL AT -->
+<!ENTITY comp "&#x02201;" ><!--COMPLEMENT -->
+<!ENTITY compfn "&#x02218;" ><!--RING OPERATOR -->
+<!ENTITY complement "&#x02201;" ><!--COMPLEMENT -->
+<!ENTITY complexes "&#x02102;" ><!--DOUBLE-STRUCK CAPITAL C -->
+<!ENTITY cong "&#x02245;" ><!--APPROXIMATELY EQUAL TO -->
+<!ENTITY congdot "&#x02A6D;" ><!--CONGRUENT WITH DOT ABOVE -->
+<!ENTITY conint "&#x0222E;" ><!--CONTOUR INTEGRAL -->
+<!ENTITY copf "&#x1D554;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL C -->
+<!ENTITY coprod "&#x02210;" ><!--N-ARY COPRODUCT -->
+<!ENTITY copy "&#x000A9;" ><!--COPYRIGHT SIGN -->
+<!ENTITY copysr "&#x02117;" ><!--SOUND RECORDING COPYRIGHT -->
+<!ENTITY crarr "&#x021B5;" ><!--DOWNWARDS ARROW WITH CORNER LEFTWARDS -->
+<!ENTITY cross "&#x02717;" ><!--BALLOT X -->
+<!ENTITY cscr "&#x1D4B8;" ><!--MATHEMATICAL SCRIPT SMALL C -->
+<!ENTITY csub "&#x02ACF;" ><!--CLOSED SUBSET -->
+<!ENTITY csube "&#x02AD1;" ><!--CLOSED SUBSET OR EQUAL TO -->
+<!ENTITY csup "&#x02AD0;" ><!--CLOSED SUPERSET -->
+<!ENTITY csupe "&#x02AD2;" ><!--CLOSED SUPERSET OR EQUAL TO -->
+<!ENTITY ctdot "&#x022EF;" ><!--MIDLINE HORIZONTAL ELLIPSIS -->
+<!ENTITY cudarrl "&#x02938;" ><!--RIGHT-SIDE ARC CLOCKWISE ARROW -->
+<!ENTITY cudarrr "&#x02935;" ><!--ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS -->
+<!ENTITY cuepr "&#x022DE;" ><!--EQUAL TO OR PRECEDES -->
+<!ENTITY cuesc "&#x022DF;" ><!--EQUAL TO OR SUCCEEDS -->
+<!ENTITY cularr "&#x021B6;" ><!--ANTICLOCKWISE TOP SEMICIRCLE ARROW -->
+<!ENTITY cularrp "&#x0293D;" ><!--TOP ARC ANTICLOCKWISE ARROW WITH PLUS -->
+<!ENTITY cup "&#x0222A;" ><!--UNION -->
+<!ENTITY cupbrcap "&#x02A48;" ><!--UNION ABOVE BAR ABOVE INTERSECTION -->
+<!ENTITY cupcap "&#x02A46;" ><!--UNION ABOVE INTERSECTION -->
+<!ENTITY cupcup "&#x02A4A;" ><!--UNION BESIDE AND JOINED WITH UNION -->
+<!ENTITY cupdot "&#x0228D;" ><!--MULTISET MULTIPLICATION -->
+<!ENTITY cupor "&#x02A45;" ><!--UNION WITH LOGICAL OR -->
+<!ENTITY cups "&#x0222A;&#x0FE00;" ><!--UNION with serifs -->
+<!ENTITY curarr "&#x021B7;" ><!--CLOCKWISE TOP SEMICIRCLE ARROW -->
+<!ENTITY curarrm "&#x0293C;" ><!--TOP ARC CLOCKWISE ARROW WITH MINUS -->
+<!ENTITY curlyeqprec "&#x022DE;" ><!--EQUAL TO OR PRECEDES -->
+<!ENTITY curlyeqsucc "&#x022DF;" ><!--EQUAL TO OR SUCCEEDS -->
+<!ENTITY curlyvee "&#x022CE;" ><!--CURLY LOGICAL OR -->
+<!ENTITY curlywedge "&#x022CF;" ><!--CURLY LOGICAL AND -->
+<!ENTITY curren "&#x000A4;" ><!--CURRENCY SIGN -->
+<!ENTITY curvearrowleft "&#x021B6;" ><!--ANTICLOCKWISE TOP SEMICIRCLE ARROW -->
+<!ENTITY curvearrowright "&#x021B7;" ><!--CLOCKWISE TOP SEMICIRCLE ARROW -->
+<!ENTITY cuvee "&#x022CE;" ><!--CURLY LOGICAL OR -->
+<!ENTITY cuwed "&#x022CF;" ><!--CURLY LOGICAL AND -->
+<!ENTITY cwconint "&#x02232;" ><!--CLOCKWISE CONTOUR INTEGRAL -->
+<!ENTITY cwint "&#x02231;" ><!--CLOCKWISE INTEGRAL -->
+<!ENTITY cylcty "&#x0232D;" ><!--CYLINDRICITY -->
+<!ENTITY dArr "&#x021D3;" ><!--DOWNWARDS DOUBLE ARROW -->
+<!ENTITY dHar "&#x02965;" ><!--DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT -->
+<!ENTITY dagger "&#x02020;" ><!--DAGGER -->
+<!ENTITY daleth "&#x02138;" ><!--DALET SYMBOL -->
+<!ENTITY darr "&#x02193;" ><!--DOWNWARDS ARROW -->
+<!ENTITY dash "&#x02010;" ><!--HYPHEN -->
+<!ENTITY dashv "&#x022A3;" ><!--LEFT TACK -->
+<!ENTITY dbkarow "&#x0290F;" ><!--RIGHTWARDS TRIPLE DASH ARROW -->
+<!ENTITY dblac "&#x002DD;" ><!--DOUBLE ACUTE ACCENT -->
+<!ENTITY dcaron "&#x0010F;" ><!--LATIN SMALL LETTER D WITH CARON -->
+<!ENTITY dcy "&#x00434;" ><!--CYRILLIC SMALL LETTER DE -->
+<!ENTITY dd "&#x02146;" ><!--DOUBLE-STRUCK ITALIC SMALL D -->
+<!ENTITY ddagger "&#x02021;" ><!--DOUBLE DAGGER -->
+<!ENTITY ddarr "&#x021CA;" ><!--DOWNWARDS PAIRED ARROWS -->
+<!ENTITY ddotseq "&#x02A77;" ><!--EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW -->
+<!ENTITY deg "&#x000B0;" ><!--DEGREE SIGN -->
+<!ENTITY delta "&#x003B4;" ><!--GREEK SMALL LETTER DELTA -->
+<!ENTITY demptyv "&#x029B1;" ><!--EMPTY SET WITH OVERBAR -->
+<!ENTITY dfisht "&#x0297F;" ><!--DOWN FISH TAIL -->
+<!ENTITY dfr "&#x1D521;" ><!--MATHEMATICAL FRAKTUR SMALL D -->
+<!ENTITY dharl "&#x021C3;" ><!--DOWNWARDS HARPOON WITH BARB LEFTWARDS -->
+<!ENTITY dharr "&#x021C2;" ><!--DOWNWARDS HARPOON WITH BARB RIGHTWARDS -->
+<!ENTITY diam "&#x022C4;" ><!--DIAMOND OPERATOR -->
+<!ENTITY diamond "&#x022C4;" ><!--DIAMOND OPERATOR -->
+<!ENTITY diamondsuit "&#x02666;" ><!--BLACK DIAMOND SUIT -->
+<!ENTITY diams "&#x02666;" ><!--BLACK DIAMOND SUIT -->
+<!ENTITY die "&#x000A8;" ><!--DIAERESIS -->
+<!ENTITY digamma "&#x003DD;" ><!--GREEK SMALL LETTER DIGAMMA -->
+<!ENTITY disin "&#x022F2;" ><!--ELEMENT OF WITH LONG HORIZONTAL STROKE -->
+<!ENTITY div "&#x000F7;" ><!--DIVISION SIGN -->
+<!ENTITY divide "&#x000F7;" ><!--DIVISION SIGN -->
+<!ENTITY divideontimes "&#x022C7;" ><!--DIVISION TIMES -->
+<!ENTITY divonx "&#x022C7;" ><!--DIVISION TIMES -->
+<!ENTITY djcy "&#x00452;" ><!--CYRILLIC SMALL LETTER DJE -->
+<!ENTITY dlcorn "&#x0231E;" ><!--BOTTOM LEFT CORNER -->
+<!ENTITY dlcrop "&#x0230D;" ><!--BOTTOM LEFT CROP -->
+<!ENTITY dollar "&#x00024;" ><!--DOLLAR SIGN -->
+<!ENTITY dopf "&#x1D555;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL D -->
+<!ENTITY dot "&#x002D9;" ><!--DOT ABOVE -->
+<!ENTITY doteq "&#x02250;" ><!--APPROACHES THE LIMIT -->
+<!ENTITY doteqdot "&#x02251;" ><!--GEOMETRICALLY EQUAL TO -->
+<!ENTITY dotminus "&#x02238;" ><!--DOT MINUS -->
+<!ENTITY dotplus "&#x02214;" ><!--DOT PLUS -->
+<!ENTITY dotsquare "&#x022A1;" ><!--SQUARED DOT OPERATOR -->
+<!ENTITY doublebarwedge "&#x02306;" ><!--PERSPECTIVE -->
+<!ENTITY downarrow "&#x02193;" ><!--DOWNWARDS ARROW -->
+<!ENTITY downdownarrows "&#x021CA;" ><!--DOWNWARDS PAIRED ARROWS -->
+<!ENTITY downharpoonleft "&#x021C3;" ><!--DOWNWARDS HARPOON WITH BARB LEFTWARDS -->
+<!ENTITY downharpoonright "&#x021C2;" ><!--DOWNWARDS HARPOON WITH BARB RIGHTWARDS -->
+<!ENTITY drbkarow "&#x02910;" ><!--RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW -->
+<!ENTITY drcorn "&#x0231F;" ><!--BOTTOM RIGHT CORNER -->
+<!ENTITY drcrop "&#x0230C;" ><!--BOTTOM RIGHT CROP -->
+<!ENTITY dscr "&#x1D4B9;" ><!--MATHEMATICAL SCRIPT SMALL D -->
+<!ENTITY dscy "&#x00455;" ><!--CYRILLIC SMALL LETTER DZE -->
+<!ENTITY dsol "&#x029F6;" ><!--SOLIDUS WITH OVERBAR -->
+<!ENTITY dstrok "&#x00111;" ><!--LATIN SMALL LETTER D WITH STROKE -->
+<!ENTITY dtdot "&#x022F1;" ><!--DOWN RIGHT DIAGONAL ELLIPSIS -->
+<!ENTITY dtri "&#x025BF;" ><!--WHITE DOWN-POINTING SMALL TRIANGLE -->
+<!ENTITY dtrif "&#x025BE;" ><!--BLACK DOWN-POINTING SMALL TRIANGLE -->
+<!ENTITY duarr "&#x021F5;" ><!--DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW -->
+<!ENTITY duhar "&#x0296F;" ><!--DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT -->
+<!ENTITY dwangle "&#x029A6;" ><!--OBLIQUE ANGLE OPENING UP -->
+<!ENTITY dzcy "&#x0045F;" ><!--CYRILLIC SMALL LETTER DZHE -->
+<!ENTITY dzigrarr "&#x027FF;" ><!--LONG RIGHTWARDS SQUIGGLE ARROW -->
+<!ENTITY eDDot "&#x02A77;" ><!--EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW -->
+<!ENTITY eDot "&#x02251;" ><!--GEOMETRICALLY EQUAL TO -->
+<!ENTITY eacute "&#x000E9;" ><!--LATIN SMALL LETTER E WITH ACUTE -->
+<!ENTITY easter "&#x02A6E;" ><!--EQUALS WITH ASTERISK -->
+<!ENTITY ecaron "&#x0011B;" ><!--LATIN SMALL LETTER E WITH CARON -->
+<!ENTITY ecir "&#x02256;" ><!--RING IN EQUAL TO -->
+<!ENTITY ecirc "&#x000EA;" ><!--LATIN SMALL LETTER E WITH CIRCUMFLEX -->
+<!ENTITY ecolon "&#x02255;" ><!--EQUALS COLON -->
+<!ENTITY ecy "&#x0044D;" ><!--CYRILLIC SMALL LETTER E -->
+<!ENTITY edot "&#x00117;" ><!--LATIN SMALL LETTER E WITH DOT ABOVE -->
+<!ENTITY ee "&#x02147;" ><!--DOUBLE-STRUCK ITALIC SMALL E -->
+<!ENTITY efDot "&#x02252;" ><!--APPROXIMATELY EQUAL TO OR THE IMAGE OF -->
+<!ENTITY efr "&#x1D522;" ><!--MATHEMATICAL FRAKTUR SMALL E -->
+<!ENTITY eg "&#x02A9A;" ><!--DOUBLE-LINE EQUAL TO OR GREATER-THAN -->
+<!ENTITY egrave "&#x000E8;" ><!--LATIN SMALL LETTER E WITH GRAVE -->
+<!ENTITY egs "&#x02A96;" ><!--SLANTED EQUAL TO OR GREATER-THAN -->
+<!ENTITY egsdot "&#x02A98;" ><!--SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE -->
+<!ENTITY el "&#x02A99;" ><!--DOUBLE-LINE EQUAL TO OR LESS-THAN -->
+<!ENTITY elinters "&#x023E7;" ><!--ELECTRICAL INTERSECTION -->
+<!ENTITY ell "&#x02113;" ><!--SCRIPT SMALL L -->
+<!ENTITY els "&#x02A95;" ><!--SLANTED EQUAL TO OR LESS-THAN -->
+<!ENTITY elsdot "&#x02A97;" ><!--SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE -->
+<!ENTITY emacr "&#x00113;" ><!--LATIN SMALL LETTER E WITH MACRON -->
+<!ENTITY empty "&#x02205;" ><!--EMPTY SET -->
+<!ENTITY emptyset "&#x02205;" ><!--EMPTY SET -->
+<!ENTITY emptyv "&#x02205;" ><!--EMPTY SET -->
+<!ENTITY emsp "&#x02003;" ><!--EM SPACE -->
+<!ENTITY emsp13 "&#x02004;" ><!--THREE-PER-EM SPACE -->
+<!ENTITY emsp14 "&#x02005;" ><!--FOUR-PER-EM SPACE -->
+<!ENTITY eng "&#x0014B;" ><!--LATIN SMALL LETTER ENG -->
+<!ENTITY ensp "&#x02002;" ><!--EN SPACE -->
+<!ENTITY eogon "&#x00119;" ><!--LATIN SMALL LETTER E WITH OGONEK -->
+<!ENTITY eopf "&#x1D556;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL E -->
+<!ENTITY epar "&#x022D5;" ><!--EQUAL AND PARALLEL TO -->
+<!ENTITY eparsl "&#x029E3;" ><!--EQUALS SIGN AND SLANTED PARALLEL -->
+<!ENTITY eplus "&#x02A71;" ><!--EQUALS SIGN ABOVE PLUS SIGN -->
+<!ENTITY epsi "&#x003B5;" ><!--GREEK SMALL LETTER EPSILON -->
+<!ENTITY epsilon "&#x003B5;" ><!--GREEK SMALL LETTER EPSILON -->
+<!ENTITY epsiv "&#x003F5;" ><!--GREEK LUNATE EPSILON SYMBOL -->
+<!ENTITY eqcirc "&#x02256;" ><!--RING IN EQUAL TO -->
+<!ENTITY eqcolon "&#x02255;" ><!--EQUALS COLON -->
+<!ENTITY eqsim "&#x02242;" ><!--MINUS TILDE -->
+<!ENTITY eqslantgtr "&#x02A96;" ><!--SLANTED EQUAL TO OR GREATER-THAN -->
+<!ENTITY eqslantless "&#x02A95;" ><!--SLANTED EQUAL TO OR LESS-THAN -->
+<!ENTITY equals "&#x0003D;" ><!--EQUALS SIGN -->
+<!ENTITY equest "&#x0225F;" ><!--QUESTIONED EQUAL TO -->
+<!ENTITY equiv "&#x02261;" ><!--IDENTICAL TO -->
+<!ENTITY equivDD "&#x02A78;" ><!--EQUIVALENT WITH FOUR DOTS ABOVE -->
+<!ENTITY eqvparsl "&#x029E5;" ><!--IDENTICAL TO AND SLANTED PARALLEL -->
+<!ENTITY erDot "&#x02253;" ><!--IMAGE OF OR APPROXIMATELY EQUAL TO -->
+<!ENTITY erarr "&#x02971;" ><!--EQUALS SIGN ABOVE RIGHTWARDS ARROW -->
+<!ENTITY escr "&#x0212F;" ><!--SCRIPT SMALL E -->
+<!ENTITY esdot "&#x02250;" ><!--APPROACHES THE LIMIT -->
+<!ENTITY esim "&#x02242;" ><!--MINUS TILDE -->
+<!ENTITY eta "&#x003B7;" ><!--GREEK SMALL LETTER ETA -->
+<!ENTITY eth "&#x000F0;" ><!--LATIN SMALL LETTER ETH -->
+<!ENTITY euml "&#x000EB;" ><!--LATIN SMALL LETTER E WITH DIAERESIS -->
+<!ENTITY euro "&#x020AC;" ><!--EURO SIGN -->
+<!ENTITY excl "&#x00021;" ><!--EXCLAMATION MARK -->
+<!ENTITY exist "&#x02203;" ><!--THERE EXISTS -->
+<!ENTITY expectation "&#x02130;" ><!--SCRIPT CAPITAL E -->
+<!ENTITY exponentiale "&#x02147;" ><!--DOUBLE-STRUCK ITALIC SMALL E -->
+<!ENTITY fallingdotseq "&#x02252;" ><!--APPROXIMATELY EQUAL TO OR THE IMAGE OF -->
+<!ENTITY fcy "&#x00444;" ><!--CYRILLIC SMALL LETTER EF -->
+<!ENTITY female "&#x02640;" ><!--FEMALE SIGN -->
+<!ENTITY ffilig "&#x0FB03;" ><!--LATIN SMALL LIGATURE FFI -->
+<!ENTITY fflig "&#x0FB00;" ><!--LATIN SMALL LIGATURE FF -->
+<!ENTITY ffllig "&#x0FB04;" ><!--LATIN SMALL LIGATURE FFL -->
+<!ENTITY ffr "&#x1D523;" ><!--MATHEMATICAL FRAKTUR SMALL F -->
+<!ENTITY filig "&#x0FB01;" ><!--LATIN SMALL LIGATURE FI -->
+<!ENTITY fjlig "&#x00066;&#x0006A;" ><!--fj ligature -->
+<!ENTITY flat "&#x0266D;" ><!--MUSIC FLAT SIGN -->
+<!ENTITY fllig "&#x0FB02;" ><!--LATIN SMALL LIGATURE FL -->
+<!ENTITY fltns "&#x025B1;" ><!--WHITE PARALLELOGRAM -->
+<!ENTITY fnof "&#x00192;" ><!--LATIN SMALL LETTER F WITH HOOK -->
+<!ENTITY fopf "&#x1D557;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL F -->
+<!ENTITY forall "&#x02200;" ><!--FOR ALL -->
+<!ENTITY fork "&#x022D4;" ><!--PITCHFORK -->
+<!ENTITY forkv "&#x02AD9;" ><!--ELEMENT OF OPENING DOWNWARDS -->
+<!ENTITY fpartint "&#x02A0D;" ><!--FINITE PART INTEGRAL -->
+<!ENTITY frac12 "&#x000BD;" ><!--VULGAR FRACTION ONE HALF -->
+<!ENTITY frac13 "&#x02153;" ><!--VULGAR FRACTION ONE THIRD -->
+<!ENTITY frac14 "&#x000BC;" ><!--VULGAR FRACTION ONE QUARTER -->
+<!ENTITY frac15 "&#x02155;" ><!--VULGAR FRACTION ONE FIFTH -->
+<!ENTITY frac16 "&#x02159;" ><!--VULGAR FRACTION ONE SIXTH -->
+<!ENTITY frac18 "&#x0215B;" ><!--VULGAR FRACTION ONE EIGHTH -->
+<!ENTITY frac23 "&#x02154;" ><!--VULGAR FRACTION TWO THIRDS -->
+<!ENTITY frac25 "&#x02156;" ><!--VULGAR FRACTION TWO FIFTHS -->
+<!ENTITY frac34 "&#x000BE;" ><!--VULGAR FRACTION THREE QUARTERS -->
+<!ENTITY frac35 "&#x02157;" ><!--VULGAR FRACTION THREE FIFTHS -->
+<!ENTITY frac38 "&#x0215C;" ><!--VULGAR FRACTION THREE EIGHTHS -->
+<!ENTITY frac45 "&#x02158;" ><!--VULGAR FRACTION FOUR FIFTHS -->
+<!ENTITY frac56 "&#x0215A;" ><!--VULGAR FRACTION FIVE SIXTHS -->
+<!ENTITY frac58 "&#x0215D;" ><!--VULGAR FRACTION FIVE EIGHTHS -->
+<!ENTITY frac78 "&#x0215E;" ><!--VULGAR FRACTION SEVEN EIGHTHS -->
+<!ENTITY frasl "&#x02044;" ><!--FRACTION SLASH -->
+<!ENTITY frown "&#x02322;" ><!--FROWN -->
+<!ENTITY fscr "&#x1D4BB;" ><!--MATHEMATICAL SCRIPT SMALL F -->
+<!ENTITY gE "&#x02267;" ><!--GREATER-THAN OVER EQUAL TO -->
+<!ENTITY gEl "&#x02A8C;" ><!--GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN -->
+<!ENTITY gacute "&#x001F5;" ><!--LATIN SMALL LETTER G WITH ACUTE -->
+<!ENTITY gamma "&#x003B3;" ><!--GREEK SMALL LETTER GAMMA -->
+<!ENTITY gammad "&#x003DD;" ><!--GREEK SMALL LETTER DIGAMMA -->
+<!ENTITY gap "&#x02A86;" ><!--GREATER-THAN OR APPROXIMATE -->
+<!ENTITY gbreve "&#x0011F;" ><!--LATIN SMALL LETTER G WITH BREVE -->
+<!ENTITY gcirc "&#x0011D;" ><!--LATIN SMALL LETTER G WITH CIRCUMFLEX -->
+<!ENTITY gcy "&#x00433;" ><!--CYRILLIC SMALL LETTER GHE -->
+<!ENTITY gdot "&#x00121;" ><!--LATIN SMALL LETTER G WITH DOT ABOVE -->
+<!ENTITY ge "&#x02265;" ><!--GREATER-THAN OR EQUAL TO -->
+<!ENTITY gel "&#x022DB;" ><!--GREATER-THAN EQUAL TO OR LESS-THAN -->
+<!ENTITY geq "&#x02265;" ><!--GREATER-THAN OR EQUAL TO -->
+<!ENTITY geqq "&#x02267;" ><!--GREATER-THAN OVER EQUAL TO -->
+<!ENTITY geqslant "&#x02A7E;" ><!--GREATER-THAN OR SLANTED EQUAL TO -->
+<!ENTITY ges "&#x02A7E;" ><!--GREATER-THAN OR SLANTED EQUAL TO -->
+<!ENTITY gescc "&#x02AA9;" ><!--GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL -->
+<!ENTITY gesdot "&#x02A80;" ><!--GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE -->
+<!ENTITY gesdoto "&#x02A82;" ><!--GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE -->
+<!ENTITY gesdotol "&#x02A84;" ><!--GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT -->
+<!ENTITY gesl "&#x022DB;&#x0FE00;" ><!--GREATER-THAN slanted EQUAL TO OR LESS-THAN -->
+<!ENTITY gesles "&#x02A94;" ><!--GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL -->
+<!ENTITY gfr "&#x1D524;" ><!--MATHEMATICAL FRAKTUR SMALL G -->
+<!ENTITY gg "&#x0226B;" ><!--MUCH GREATER-THAN -->
+<!ENTITY ggg "&#x022D9;" ><!--VERY MUCH GREATER-THAN -->
+<!ENTITY gimel "&#x02137;" ><!--GIMEL SYMBOL -->
+<!ENTITY gjcy "&#x00453;" ><!--CYRILLIC SMALL LETTER GJE -->
+<!ENTITY gl "&#x02277;" ><!--GREATER-THAN OR LESS-THAN -->
+<!ENTITY glE "&#x02A92;" ><!--GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL -->
+<!ENTITY gla "&#x02AA5;" ><!--GREATER-THAN BESIDE LESS-THAN -->
+<!ENTITY glj "&#x02AA4;" ><!--GREATER-THAN OVERLAPPING LESS-THAN -->
+<!ENTITY gnE "&#x02269;" ><!--GREATER-THAN BUT NOT EQUAL TO -->
+<!ENTITY gnap "&#x02A8A;" ><!--GREATER-THAN AND NOT APPROXIMATE -->
+<!ENTITY gnapprox "&#x02A8A;" ><!--GREATER-THAN AND NOT APPROXIMATE -->
+<!ENTITY gne "&#x02A88;" ><!--GREATER-THAN AND SINGLE-LINE NOT EQUAL TO -->
+<!ENTITY gneq "&#x02A88;" ><!--GREATER-THAN AND SINGLE-LINE NOT EQUAL TO -->
+<!ENTITY gneqq "&#x02269;" ><!--GREATER-THAN BUT NOT EQUAL TO -->
+<!ENTITY gnsim "&#x022E7;" ><!--GREATER-THAN BUT NOT EQUIVALENT TO -->
+<!ENTITY gopf "&#x1D558;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL G -->
+<!ENTITY grave "&#x00060;" ><!--GRAVE ACCENT -->
+<!ENTITY gscr "&#x0210A;" ><!--SCRIPT SMALL G -->
+<!ENTITY gsim "&#x02273;" ><!--GREATER-THAN OR EQUIVALENT TO -->
+<!ENTITY gsime "&#x02A8E;" ><!--GREATER-THAN ABOVE SIMILAR OR EQUAL -->
+<!ENTITY gsiml "&#x02A90;" ><!--GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN -->
+<!ENTITY gt "&#x0003E;" ><!--GREATER-THAN SIGN -->
+<!ENTITY gtcc "&#x02AA7;" ><!--GREATER-THAN CLOSED BY CURVE -->
+<!ENTITY gtcir "&#x02A7A;" ><!--GREATER-THAN WITH CIRCLE INSIDE -->
+<!ENTITY gtdot "&#x022D7;" ><!--GREATER-THAN WITH DOT -->
+<!ENTITY gtlPar "&#x02995;" ><!--DOUBLE LEFT ARC GREATER-THAN BRACKET -->
+<!ENTITY gtquest "&#x02A7C;" ><!--GREATER-THAN WITH QUESTION MARK ABOVE -->
+<!ENTITY gtrapprox "&#x02A86;" ><!--GREATER-THAN OR APPROXIMATE -->
+<!ENTITY gtrarr "&#x02978;" ><!--GREATER-THAN ABOVE RIGHTWARDS ARROW -->
+<!ENTITY gtrdot "&#x022D7;" ><!--GREATER-THAN WITH DOT -->
+<!ENTITY gtreqless "&#x022DB;" ><!--GREATER-THAN EQUAL TO OR LESS-THAN -->
+<!ENTITY gtreqqless "&#x02A8C;" ><!--GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN -->
+<!ENTITY gtrless "&#x02277;" ><!--GREATER-THAN OR LESS-THAN -->
+<!ENTITY gtrsim "&#x02273;" ><!--GREATER-THAN OR EQUIVALENT TO -->
+<!ENTITY gvertneqq "&#x02269;&#x0FE00;" ><!--GREATER-THAN BUT NOT EQUAL TO - with vertical stroke -->
+<!ENTITY gvnE "&#x02269;&#x0FE00;" ><!--GREATER-THAN BUT NOT EQUAL TO - with vertical stroke -->
+<!ENTITY hArr "&#x021D4;" ><!--LEFT RIGHT DOUBLE ARROW -->
+<!ENTITY hairsp "&#x0200A;" ><!--HAIR SPACE -->
+<!ENTITY half "&#x000BD;" ><!--VULGAR FRACTION ONE HALF -->
+<!ENTITY hamilt "&#x0210B;" ><!--SCRIPT CAPITAL H -->
+<!ENTITY hardcy "&#x0044A;" ><!--CYRILLIC SMALL LETTER HARD SIGN -->
+<!ENTITY harr "&#x02194;" ><!--LEFT RIGHT ARROW -->
+<!ENTITY harrcir "&#x02948;" ><!--LEFT RIGHT ARROW THROUGH SMALL CIRCLE -->
+<!ENTITY harrw "&#x021AD;" ><!--LEFT RIGHT WAVE ARROW -->
+<!ENTITY hbar "&#x0210F;" ><!--PLANCK CONSTANT OVER TWO PI -->
+<!ENTITY hcirc "&#x00125;" ><!--LATIN SMALL LETTER H WITH CIRCUMFLEX -->
+<!ENTITY hearts "&#x02665;" ><!--BLACK HEART SUIT -->
+<!ENTITY heartsuit "&#x02665;" ><!--BLACK HEART SUIT -->
+<!ENTITY hellip "&#x02026;" ><!--HORIZONTAL ELLIPSIS -->
+<!ENTITY hercon "&#x022B9;" ><!--HERMITIAN CONJUGATE MATRIX -->
+<!ENTITY hfr "&#x1D525;" ><!--MATHEMATICAL FRAKTUR SMALL H -->
+<!ENTITY hksearow "&#x02925;" ><!--SOUTH EAST ARROW WITH HOOK -->
+<!ENTITY hkswarow "&#x02926;" ><!--SOUTH WEST ARROW WITH HOOK -->
+<!ENTITY hoarr "&#x021FF;" ><!--LEFT RIGHT OPEN-HEADED ARROW -->
+<!ENTITY homtht "&#x0223B;" ><!--HOMOTHETIC -->
+<!ENTITY hookleftarrow "&#x021A9;" ><!--LEFTWARDS ARROW WITH HOOK -->
+<!ENTITY hookrightarrow "&#x021AA;" ><!--RIGHTWARDS ARROW WITH HOOK -->
+<!ENTITY hopf "&#x1D559;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL H -->
+<!ENTITY horbar "&#x02015;" ><!--HORIZONTAL BAR -->
+<!ENTITY hscr "&#x1D4BD;" ><!--MATHEMATICAL SCRIPT SMALL H -->
+<!ENTITY hslash "&#x0210F;" ><!--PLANCK CONSTANT OVER TWO PI -->
+<!ENTITY hstrok "&#x00127;" ><!--LATIN SMALL LETTER H WITH STROKE -->
+<!ENTITY hybull "&#x02043;" ><!--HYPHEN BULLET -->
+<!ENTITY hyphen "&#x02010;" ><!--HYPHEN -->
+<!ENTITY iacute "&#x000ED;" ><!--LATIN SMALL LETTER I WITH ACUTE -->
+<!ENTITY ic "&#x02063;" ><!--INVISIBLE SEPARATOR -->
+<!ENTITY icirc "&#x000EE;" ><!--LATIN SMALL LETTER I WITH CIRCUMFLEX -->
+<!ENTITY icy "&#x00438;" ><!--CYRILLIC SMALL LETTER I -->
+<!ENTITY iecy "&#x00435;" ><!--CYRILLIC SMALL LETTER IE -->
+<!ENTITY iexcl "&#x000A1;" ><!--INVERTED EXCLAMATION MARK -->
+<!ENTITY iff "&#x021D4;" ><!--LEFT RIGHT DOUBLE ARROW -->
+<!ENTITY ifr "&#x1D526;" ><!--MATHEMATICAL FRAKTUR SMALL I -->
+<!ENTITY igrave "&#x000EC;" ><!--LATIN SMALL LETTER I WITH GRAVE -->
+<!ENTITY ii "&#x02148;" ><!--DOUBLE-STRUCK ITALIC SMALL I -->
+<!ENTITY iiiint "&#x02A0C;" ><!--QUADRUPLE INTEGRAL OPERATOR -->
+<!ENTITY iiint "&#x0222D;" ><!--TRIPLE INTEGRAL -->
+<!ENTITY iinfin "&#x029DC;" ><!--INCOMPLETE INFINITY -->
+<!ENTITY iiota "&#x02129;" ><!--TURNED GREEK SMALL LETTER IOTA -->
+<!ENTITY ijlig "&#x00133;" ><!--LATIN SMALL LIGATURE IJ -->
+<!ENTITY imacr "&#x0012B;" ><!--LATIN SMALL LETTER I WITH MACRON -->
+<!ENTITY image "&#x02111;" ><!--BLACK-LETTER CAPITAL I -->
+<!ENTITY imagline "&#x02110;" ><!--SCRIPT CAPITAL I -->
+<!ENTITY imagpart "&#x02111;" ><!--BLACK-LETTER CAPITAL I -->
+<!ENTITY imath "&#x00131;" ><!--LATIN SMALL LETTER DOTLESS I -->
+<!ENTITY imof "&#x022B7;" ><!--IMAGE OF -->
+<!ENTITY imped "&#x001B5;" ><!--LATIN CAPITAL LETTER Z WITH STROKE -->
+<!ENTITY in "&#x02208;" ><!--ELEMENT OF -->
+<!ENTITY incare "&#x02105;" ><!--CARE OF -->
+<!ENTITY infin "&#x0221E;" ><!--INFINITY -->
+<!ENTITY infintie "&#x029DD;" ><!--TIE OVER INFINITY -->
+<!ENTITY inodot "&#x00131;" ><!--LATIN SMALL LETTER DOTLESS I -->
+<!ENTITY int "&#x0222B;" ><!--INTEGRAL -->
+<!ENTITY intcal "&#x022BA;" ><!--INTERCALATE -->
+<!ENTITY integers "&#x02124;" ><!--DOUBLE-STRUCK CAPITAL Z -->
+<!ENTITY intercal "&#x022BA;" ><!--INTERCALATE -->
+<!ENTITY intlarhk "&#x02A17;" ><!--INTEGRAL WITH LEFTWARDS ARROW WITH HOOK -->
+<!ENTITY intprod "&#x02A3C;" ><!--INTERIOR PRODUCT -->
+<!ENTITY iocy "&#x00451;" ><!--CYRILLIC SMALL LETTER IO -->
+<!ENTITY iogon "&#x0012F;" ><!--LATIN SMALL LETTER I WITH OGONEK -->
+<!ENTITY iopf "&#x1D55A;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL I -->
+<!ENTITY iota "&#x003B9;" ><!--GREEK SMALL LETTER IOTA -->
+<!ENTITY iprod "&#x02A3C;" ><!--INTERIOR PRODUCT -->
+<!ENTITY iquest "&#x000BF;" ><!--INVERTED QUESTION MARK -->
+<!ENTITY iscr "&#x1D4BE;" ><!--MATHEMATICAL SCRIPT SMALL I -->
+<!ENTITY isin "&#x02208;" ><!--ELEMENT OF -->
+<!ENTITY isinE "&#x022F9;" ><!--ELEMENT OF WITH TWO HORIZONTAL STROKES -->
+<!ENTITY isindot "&#x022F5;" ><!--ELEMENT OF WITH DOT ABOVE -->
+<!ENTITY isins "&#x022F4;" ><!--SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE -->
+<!ENTITY isinsv "&#x022F3;" ><!--ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE -->
+<!ENTITY isinv "&#x02208;" ><!--ELEMENT OF -->
+<!ENTITY it "&#x02062;" ><!--INVISIBLE TIMES -->
+<!ENTITY itilde "&#x00129;" ><!--LATIN SMALL LETTER I WITH TILDE -->
+<!ENTITY iukcy "&#x00456;" ><!--CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I -->
+<!ENTITY iuml "&#x000EF;" ><!--LATIN SMALL LETTER I WITH DIAERESIS -->
+<!ENTITY jcirc "&#x00135;" ><!--LATIN SMALL LETTER J WITH CIRCUMFLEX -->
+<!ENTITY jcy "&#x00439;" ><!--CYRILLIC SMALL LETTER SHORT I -->
+<!ENTITY jfr "&#x1D527;" ><!--MATHEMATICAL FRAKTUR SMALL J -->
+<!ENTITY jmath "&#x00237;" ><!--LATIN SMALL LETTER DOTLESS J -->
+<!ENTITY jopf "&#x1D55B;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL J -->
+<!ENTITY jscr "&#x1D4BF;" ><!--MATHEMATICAL SCRIPT SMALL J -->
+<!ENTITY jsercy "&#x00458;" ><!--CYRILLIC SMALL LETTER JE -->
+<!ENTITY jukcy "&#x00454;" ><!--CYRILLIC SMALL LETTER UKRAINIAN IE -->
+<!ENTITY kappa "&#x003BA;" ><!--GREEK SMALL LETTER KAPPA -->
+<!ENTITY kappav "&#x003F0;" ><!--GREEK KAPPA SYMBOL -->
+<!ENTITY kcedil "&#x00137;" ><!--LATIN SMALL LETTER K WITH CEDILLA -->
+<!ENTITY kcy "&#x0043A;" ><!--CYRILLIC SMALL LETTER KA -->
+<!ENTITY kfr "&#x1D528;" ><!--MATHEMATICAL FRAKTUR SMALL K -->
+<!ENTITY kgreen "&#x00138;" ><!--LATIN SMALL LETTER KRA -->
+<!ENTITY khcy "&#x00445;" ><!--CYRILLIC SMALL LETTER HA -->
+<!ENTITY kjcy "&#x0045C;" ><!--CYRILLIC SMALL LETTER KJE -->
+<!ENTITY kopf "&#x1D55C;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL K -->
+<!ENTITY kscr "&#x1D4C0;" ><!--MATHEMATICAL SCRIPT SMALL K -->
+<!ENTITY lAarr "&#x021DA;" ><!--LEFTWARDS TRIPLE ARROW -->
+<!ENTITY lArr "&#x021D0;" ><!--LEFTWARDS DOUBLE ARROW -->
+<!ENTITY lAtail "&#x0291B;" ><!--LEFTWARDS DOUBLE ARROW-TAIL -->
+<!ENTITY lBarr "&#x0290E;" ><!--LEFTWARDS TRIPLE DASH ARROW -->
+<!ENTITY lE "&#x02266;" ><!--LESS-THAN OVER EQUAL TO -->
+<!ENTITY lEg "&#x02A8B;" ><!--LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN -->
+<!ENTITY lHar "&#x02962;" ><!--LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN -->
+<!ENTITY lacute "&#x0013A;" ><!--LATIN SMALL LETTER L WITH ACUTE -->
+<!ENTITY laemptyv "&#x029B4;" ><!--EMPTY SET WITH LEFT ARROW ABOVE -->
+<!ENTITY lagran "&#x02112;" ><!--SCRIPT CAPITAL L -->
+<!ENTITY lambda "&#x003BB;" ><!--GREEK SMALL LETTER LAMDA -->
+<!ENTITY lang "&#x027E8;" ><!--MATHEMATICAL LEFT ANGLE BRACKET -->
+<!ENTITY langd "&#x02991;" ><!--LEFT ANGLE BRACKET WITH DOT -->
+<!ENTITY langle "&#x027E8;" ><!--MATHEMATICAL LEFT ANGLE BRACKET -->
+<!ENTITY lap "&#x02A85;" ><!--LESS-THAN OR APPROXIMATE -->
+<!ENTITY laquo "&#x000AB;" ><!--LEFT-POINTING DOUBLE ANGLE QUOTATION MARK -->
+<!ENTITY larr "&#x02190;" ><!--LEFTWARDS ARROW -->
+<!ENTITY larrb "&#x021E4;" ><!--LEFTWARDS ARROW TO BAR -->
+<!ENTITY larrbfs "&#x0291F;" ><!--LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND -->
+<!ENTITY larrfs "&#x0291D;" ><!--LEFTWARDS ARROW TO BLACK DIAMOND -->
+<!ENTITY larrhk "&#x021A9;" ><!--LEFTWARDS ARROW WITH HOOK -->
+<!ENTITY larrlp "&#x021AB;" ><!--LEFTWARDS ARROW WITH LOOP -->
+<!ENTITY larrpl "&#x02939;" ><!--LEFT-SIDE ARC ANTICLOCKWISE ARROW -->
+<!ENTITY larrsim "&#x02973;" ><!--LEFTWARDS ARROW ABOVE TILDE OPERATOR -->
+<!ENTITY larrtl "&#x021A2;" ><!--LEFTWARDS ARROW WITH TAIL -->
+<!ENTITY lat "&#x02AAB;" ><!--LARGER THAN -->
+<!ENTITY latail "&#x02919;" ><!--LEFTWARDS ARROW-TAIL -->
+<!ENTITY late "&#x02AAD;" ><!--LARGER THAN OR EQUAL TO -->
+<!ENTITY lates "&#x02AAD;&#x0FE00;" ><!--LARGER THAN OR slanted EQUAL -->
+<!ENTITY lbarr "&#x0290C;" ><!--LEFTWARDS DOUBLE DASH ARROW -->
+<!ENTITY lbbrk "&#x02772;" ><!--LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT -->
+<!ENTITY lbrace "&#x0007B;" ><!--LEFT CURLY BRACKET -->
+<!ENTITY lbrack "&#x0005B;" ><!--LEFT SQUARE BRACKET -->
+<!ENTITY lbrke "&#x0298B;" ><!--LEFT SQUARE BRACKET WITH UNDERBAR -->
+<!ENTITY lbrksld "&#x0298F;" ><!--LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER -->
+<!ENTITY lbrkslu "&#x0298D;" ><!--LEFT SQUARE BRACKET WITH TICK IN TOP CORNER -->
+<!ENTITY lcaron "&#x0013E;" ><!--LATIN SMALL LETTER L WITH CARON -->
+<!ENTITY lcedil "&#x0013C;" ><!--LATIN SMALL LETTER L WITH CEDILLA -->
+<!ENTITY lceil "&#x02308;" ><!--LEFT CEILING -->
+<!ENTITY lcub "&#x0007B;" ><!--LEFT CURLY BRACKET -->
+<!ENTITY lcy "&#x0043B;" ><!--CYRILLIC SMALL LETTER EL -->
+<!ENTITY ldca "&#x02936;" ><!--ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS -->
+<!ENTITY ldquo "&#x0201C;" ><!--LEFT DOUBLE QUOTATION MARK -->
+<!ENTITY ldquor "&#x0201E;" ><!--DOUBLE LOW-9 QUOTATION MARK -->
+<!ENTITY ldrdhar "&#x02967;" ><!--LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN -->
+<!ENTITY ldrushar "&#x0294B;" ><!--LEFT BARB DOWN RIGHT BARB UP HARPOON -->
+<!ENTITY ldsh "&#x021B2;" ><!--DOWNWARDS ARROW WITH TIP LEFTWARDS -->
+<!ENTITY le "&#x02264;" ><!--LESS-THAN OR EQUAL TO -->
+<!ENTITY leftarrow "&#x02190;" ><!--LEFTWARDS ARROW -->
+<!ENTITY leftarrowtail "&#x021A2;" ><!--LEFTWARDS ARROW WITH TAIL -->
+<!ENTITY leftharpoondown "&#x021BD;" ><!--LEFTWARDS HARPOON WITH BARB DOWNWARDS -->
+<!ENTITY leftharpoonup "&#x021BC;" ><!--LEFTWARDS HARPOON WITH BARB UPWARDS -->
+<!ENTITY leftleftarrows "&#x021C7;" ><!--LEFTWARDS PAIRED ARROWS -->
+<!ENTITY leftrightarrow "&#x02194;" ><!--LEFT RIGHT ARROW -->
+<!ENTITY leftrightarrows "&#x021C6;" ><!--LEFTWARDS ARROW OVER RIGHTWARDS ARROW -->
+<!ENTITY leftrightharpoons "&#x021CB;" ><!--LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON -->
+<!ENTITY leftrightsquigarrow "&#x021AD;" ><!--LEFT RIGHT WAVE ARROW -->
+<!ENTITY leftthreetimes "&#x022CB;" ><!--LEFT SEMIDIRECT PRODUCT -->
+<!ENTITY leg "&#x022DA;" ><!--LESS-THAN EQUAL TO OR GREATER-THAN -->
+<!ENTITY leq "&#x02264;" ><!--LESS-THAN OR EQUAL TO -->
+<!ENTITY leqq "&#x02266;" ><!--LESS-THAN OVER EQUAL TO -->
+<!ENTITY leqslant "&#x02A7D;" ><!--LESS-THAN OR SLANTED EQUAL TO -->
+<!ENTITY les "&#x02A7D;" ><!--LESS-THAN OR SLANTED EQUAL TO -->
+<!ENTITY lescc "&#x02AA8;" ><!--LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL -->
+<!ENTITY lesdot "&#x02A7F;" ><!--LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE -->
+<!ENTITY lesdoto "&#x02A81;" ><!--LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE -->
+<!ENTITY lesdotor "&#x02A83;" ><!--LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT -->
+<!ENTITY lesg "&#x022DA;&#x0FE00;" ><!--LESS-THAN slanted EQUAL TO OR GREATER-THAN -->
+<!ENTITY lesges "&#x02A93;" ><!--LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL -->
+<!ENTITY lessapprox "&#x02A85;" ><!--LESS-THAN OR APPROXIMATE -->
+<!ENTITY lessdot "&#x022D6;" ><!--LESS-THAN WITH DOT -->
+<!ENTITY lesseqgtr "&#x022DA;" ><!--LESS-THAN EQUAL TO OR GREATER-THAN -->
+<!ENTITY lesseqqgtr "&#x02A8B;" ><!--LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN -->
+<!ENTITY lessgtr "&#x02276;" ><!--LESS-THAN OR GREATER-THAN -->
+<!ENTITY lesssim "&#x02272;" ><!--LESS-THAN OR EQUIVALENT TO -->
+<!ENTITY lfisht "&#x0297C;" ><!--LEFT FISH TAIL -->
+<!ENTITY lfloor "&#x0230A;" ><!--LEFT FLOOR -->
+<!ENTITY lfr "&#x1D529;" ><!--MATHEMATICAL FRAKTUR SMALL L -->
+<!ENTITY lg "&#x02276;" ><!--LESS-THAN OR GREATER-THAN -->
+<!ENTITY lgE "&#x02A91;" ><!--LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL -->
+<!ENTITY lhard "&#x021BD;" ><!--LEFTWARDS HARPOON WITH BARB DOWNWARDS -->
+<!ENTITY lharu "&#x021BC;" ><!--LEFTWARDS HARPOON WITH BARB UPWARDS -->
+<!ENTITY lharul "&#x0296A;" ><!--LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH -->
+<!ENTITY lhblk "&#x02584;" ><!--LOWER HALF BLOCK -->
+<!ENTITY ljcy "&#x00459;" ><!--CYRILLIC SMALL LETTER LJE -->
+<!ENTITY ll "&#x0226A;" ><!--MUCH LESS-THAN -->
+<!ENTITY llarr "&#x021C7;" ><!--LEFTWARDS PAIRED ARROWS -->
+<!ENTITY llcorner "&#x0231E;" ><!--BOTTOM LEFT CORNER -->
+<!ENTITY llhard "&#x0296B;" ><!--LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH -->
+<!ENTITY lltri "&#x025FA;" ><!--LOWER LEFT TRIANGLE -->
+<!ENTITY lmidot "&#x00140;" ><!--LATIN SMALL LETTER L WITH MIDDLE DOT -->
+<!ENTITY lmoust "&#x023B0;" ><!--UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION -->
+<!ENTITY lmoustache "&#x023B0;" ><!--UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION -->
+<!ENTITY lnE "&#x02268;" ><!--LESS-THAN BUT NOT EQUAL TO -->
+<!ENTITY lnap "&#x02A89;" ><!--LESS-THAN AND NOT APPROXIMATE -->
+<!ENTITY lnapprox "&#x02A89;" ><!--LESS-THAN AND NOT APPROXIMATE -->
+<!ENTITY lne "&#x02A87;" ><!--LESS-THAN AND SINGLE-LINE NOT EQUAL TO -->
+<!ENTITY lneq "&#x02A87;" ><!--LESS-THAN AND SINGLE-LINE NOT EQUAL TO -->
+<!ENTITY lneqq "&#x02268;" ><!--LESS-THAN BUT NOT EQUAL TO -->
+<!ENTITY lnsim "&#x022E6;" ><!--LESS-THAN BUT NOT EQUIVALENT TO -->
+<!ENTITY loang "&#x027EC;" ><!--MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET -->
+<!ENTITY loarr "&#x021FD;" ><!--LEFTWARDS OPEN-HEADED ARROW -->
+<!ENTITY lobrk "&#x027E6;" ><!--MATHEMATICAL LEFT WHITE SQUARE BRACKET -->
+<!ENTITY longleftarrow "&#x027F5;" ><!--LONG LEFTWARDS ARROW -->
+<!ENTITY longleftrightarrow "&#x027F7;" ><!--LONG LEFT RIGHT ARROW -->
+<!ENTITY longmapsto "&#x027FC;" ><!--LONG RIGHTWARDS ARROW FROM BAR -->
+<!ENTITY longrightarrow "&#x027F6;" ><!--LONG RIGHTWARDS ARROW -->
+<!ENTITY looparrowleft "&#x021AB;" ><!--LEFTWARDS ARROW WITH LOOP -->
+<!ENTITY looparrowright "&#x021AC;" ><!--RIGHTWARDS ARROW WITH LOOP -->
+<!ENTITY lopar "&#x02985;" ><!--LEFT WHITE PARENTHESIS -->
+<!ENTITY lopf "&#x1D55D;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL L -->
+<!ENTITY loplus "&#x02A2D;" ><!--PLUS SIGN IN LEFT HALF CIRCLE -->
+<!ENTITY lotimes "&#x02A34;" ><!--MULTIPLICATION SIGN IN LEFT HALF CIRCLE -->
+<!ENTITY lowast "&#x02217;" ><!--ASTERISK OPERATOR -->
+<!ENTITY lowbar "&#x0005F;" ><!--LOW LINE -->
+<!ENTITY loz "&#x025CA;" ><!--LOZENGE -->
+<!ENTITY lozenge "&#x025CA;" ><!--LOZENGE -->
+<!ENTITY lozf "&#x029EB;" ><!--BLACK LOZENGE -->
+<!ENTITY lpar "&#x00028;" ><!--LEFT PARENTHESIS -->
+<!ENTITY lparlt "&#x02993;" ><!--LEFT ARC LESS-THAN BRACKET -->
+<!ENTITY lrarr "&#x021C6;" ><!--LEFTWARDS ARROW OVER RIGHTWARDS ARROW -->
+<!ENTITY lrcorner "&#x0231F;" ><!--BOTTOM RIGHT CORNER -->
+<!ENTITY lrhar "&#x021CB;" ><!--LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON -->
+<!ENTITY lrhard "&#x0296D;" ><!--RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH -->
+<!ENTITY lrm "&#x0200E;" ><!--LEFT-TO-RIGHT MARK -->
+<!ENTITY lrtri "&#x022BF;" ><!--RIGHT TRIANGLE -->
+<!ENTITY lsaquo "&#x02039;" ><!--SINGLE LEFT-POINTING ANGLE QUOTATION MARK -->
+<!ENTITY lscr "&#x1D4C1;" ><!--MATHEMATICAL SCRIPT SMALL L -->
+<!ENTITY lsh "&#x021B0;" ><!--UPWARDS ARROW WITH TIP LEFTWARDS -->
+<!ENTITY lsim "&#x02272;" ><!--LESS-THAN OR EQUIVALENT TO -->
+<!ENTITY lsime "&#x02A8D;" ><!--LESS-THAN ABOVE SIMILAR OR EQUAL -->
+<!ENTITY lsimg "&#x02A8F;" ><!--LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN -->
+<!ENTITY lsqb "&#x0005B;" ><!--LEFT SQUARE BRACKET -->
+<!ENTITY lsquo "&#x02018;" ><!--LEFT SINGLE QUOTATION MARK -->
+<!ENTITY lsquor "&#x0201A;" ><!--SINGLE LOW-9 QUOTATION MARK -->
+<!ENTITY lstrok "&#x00142;" ><!--LATIN SMALL LETTER L WITH STROKE -->
+<!ENTITY lt "&#38;#60;" ><!--LESS-THAN SIGN -->
+<!ENTITY ltcc "&#x02AA6;" ><!--LESS-THAN CLOSED BY CURVE -->
+<!ENTITY ltcir "&#x02A79;" ><!--LESS-THAN WITH CIRCLE INSIDE -->
+<!ENTITY ltdot "&#x022D6;" ><!--LESS-THAN WITH DOT -->
+<!ENTITY lthree "&#x022CB;" ><!--LEFT SEMIDIRECT PRODUCT -->
+<!ENTITY ltimes "&#x022C9;" ><!--LEFT NORMAL FACTOR SEMIDIRECT PRODUCT -->
+<!ENTITY ltlarr "&#x02976;" ><!--LESS-THAN ABOVE LEFTWARDS ARROW -->
+<!ENTITY ltquest "&#x02A7B;" ><!--LESS-THAN WITH QUESTION MARK ABOVE -->
+<!ENTITY ltrPar "&#x02996;" ><!--DOUBLE RIGHT ARC LESS-THAN BRACKET -->
+<!ENTITY ltri "&#x025C3;" ><!--WHITE LEFT-POINTING SMALL TRIANGLE -->
+<!ENTITY ltrie "&#x022B4;" ><!--NORMAL SUBGROUP OF OR EQUAL TO -->
+<!ENTITY ltrif "&#x025C2;" ><!--BLACK LEFT-POINTING SMALL TRIANGLE -->
+<!ENTITY lurdshar "&#x0294A;" ><!--LEFT BARB UP RIGHT BARB DOWN HARPOON -->
+<!ENTITY luruhar "&#x02966;" ><!--LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP -->
+<!ENTITY lvertneqq "&#x02268;&#x0FE00;" ><!--LESS-THAN BUT NOT EQUAL TO - with vertical stroke -->
+<!ENTITY lvnE "&#x02268;&#x0FE00;" ><!--LESS-THAN BUT NOT EQUAL TO - with vertical stroke -->
+<!ENTITY mDDot "&#x0223A;" ><!--GEOMETRIC PROPORTION -->
+<!ENTITY macr "&#x000AF;" ><!--MACRON -->
+<!ENTITY male "&#x02642;" ><!--MALE SIGN -->
+<!ENTITY malt "&#x02720;" ><!--MALTESE CROSS -->
+<!ENTITY maltese "&#x02720;" ><!--MALTESE CROSS -->
+<!ENTITY map "&#x021A6;" ><!--RIGHTWARDS ARROW FROM BAR -->
+<!ENTITY mapsto "&#x021A6;" ><!--RIGHTWARDS ARROW FROM BAR -->
+<!ENTITY mapstodown "&#x021A7;" ><!--DOWNWARDS ARROW FROM BAR -->
+<!ENTITY mapstoleft "&#x021A4;" ><!--LEFTWARDS ARROW FROM BAR -->
+<!ENTITY mapstoup "&#x021A5;" ><!--UPWARDS ARROW FROM BAR -->
+<!ENTITY marker "&#x025AE;" ><!--BLACK VERTICAL RECTANGLE -->
+<!ENTITY mcomma "&#x02A29;" ><!--MINUS SIGN WITH COMMA ABOVE -->
+<!ENTITY mcy "&#x0043C;" ><!--CYRILLIC SMALL LETTER EM -->
+<!ENTITY mdash "&#x02014;" ><!--EM DASH -->
+<!ENTITY measuredangle "&#x02221;" ><!--MEASURED ANGLE -->
+<!ENTITY mfr "&#x1D52A;" ><!--MATHEMATICAL FRAKTUR SMALL M -->
+<!ENTITY mho "&#x02127;" ><!--INVERTED OHM SIGN -->
+<!ENTITY micro "&#x000B5;" ><!--MICRO SIGN -->
+<!ENTITY mid "&#x02223;" ><!--DIVIDES -->
+<!ENTITY midast "&#x0002A;" ><!--ASTERISK -->
+<!ENTITY midcir "&#x02AF0;" ><!--VERTICAL LINE WITH CIRCLE BELOW -->
+<!ENTITY middot "&#x000B7;" ><!--MIDDLE DOT -->
+<!ENTITY minus "&#x02212;" ><!--MINUS SIGN -->
+<!ENTITY minusb "&#x0229F;" ><!--SQUARED MINUS -->
+<!ENTITY minusd "&#x02238;" ><!--DOT MINUS -->
+<!ENTITY minusdu "&#x02A2A;" ><!--MINUS SIGN WITH DOT BELOW -->
+<!ENTITY mlcp "&#x02ADB;" ><!--TRANSVERSAL INTERSECTION -->
+<!ENTITY mldr "&#x02026;" ><!--HORIZONTAL ELLIPSIS -->
+<!ENTITY mnplus "&#x02213;" ><!--MINUS-OR-PLUS SIGN -->
+<!ENTITY models "&#x022A7;" ><!--MODELS -->
+<!ENTITY mopf "&#x1D55E;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL M -->
+<!ENTITY mp "&#x02213;" ><!--MINUS-OR-PLUS SIGN -->
+<!ENTITY mscr "&#x1D4C2;" ><!--MATHEMATICAL SCRIPT SMALL M -->
+<!ENTITY mstpos "&#x0223E;" ><!--INVERTED LAZY S -->
+<!ENTITY mu "&#x003BC;" ><!--GREEK SMALL LETTER MU -->
+<!ENTITY multimap "&#x022B8;" ><!--MULTIMAP -->
+<!ENTITY mumap "&#x022B8;" ><!--MULTIMAP -->
+<!ENTITY nGg "&#x022D9;&#x00338;" ><!--VERY MUCH GREATER-THAN with slash -->
+<!ENTITY nGt "&#x0226B;&#x020D2;" ><!--MUCH GREATER THAN with vertical line -->
+<!ENTITY nGtv "&#x0226B;&#x00338;" ><!--MUCH GREATER THAN with slash -->
+<!ENTITY nLeftarrow "&#x021CD;" ><!--LEFTWARDS DOUBLE ARROW WITH STROKE -->
+<!ENTITY nLeftrightarrow "&#x021CE;" ><!--LEFT RIGHT DOUBLE ARROW WITH STROKE -->
+<!ENTITY nLl "&#x022D8;&#x00338;" ><!--VERY MUCH LESS-THAN with slash -->
+<!ENTITY nLt "&#x0226A;&#x020D2;" ><!--MUCH LESS THAN with vertical line -->
+<!ENTITY nLtv "&#x0226A;&#x00338;" ><!--MUCH LESS THAN with slash -->
+<!ENTITY nRightarrow "&#x021CF;" ><!--RIGHTWARDS DOUBLE ARROW WITH STROKE -->
+<!ENTITY nVDash "&#x022AF;" ><!--NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE -->
+<!ENTITY nVdash "&#x022AE;" ><!--DOES NOT FORCE -->
+<!ENTITY nabla "&#x02207;" ><!--NABLA -->
+<!ENTITY nacute "&#x00144;" ><!--LATIN SMALL LETTER N WITH ACUTE -->
+<!ENTITY nang "&#x02220;&#x020D2;" ><!--ANGLE with vertical line -->
+<!ENTITY nap "&#x02249;" ><!--NOT ALMOST EQUAL TO -->
+<!ENTITY napE "&#x02A70;&#x00338;" ><!--APPROXIMATELY EQUAL OR EQUAL TO with slash -->
+<!ENTITY napid "&#x0224B;&#x00338;" ><!--TRIPLE TILDE with slash -->
+<!ENTITY napos "&#x00149;" ><!--LATIN SMALL LETTER N PRECEDED BY APOSTROPHE -->
+<!ENTITY napprox "&#x02249;" ><!--NOT ALMOST EQUAL TO -->
+<!ENTITY natur "&#x0266E;" ><!--MUSIC NATURAL SIGN -->
+<!ENTITY natural "&#x0266E;" ><!--MUSIC NATURAL SIGN -->
+<!ENTITY naturals "&#x02115;" ><!--DOUBLE-STRUCK CAPITAL N -->
+<!ENTITY nbsp "&#x000A0;" ><!--NO-BREAK SPACE -->
+<!ENTITY nbump "&#x0224E;&#x00338;" ><!--GEOMETRICALLY EQUIVALENT TO with slash -->
+<!ENTITY nbumpe "&#x0224F;&#x00338;" ><!--DIFFERENCE BETWEEN with slash -->
+<!ENTITY ncap "&#x02A43;" ><!--INTERSECTION WITH OVERBAR -->
+<!ENTITY ncaron "&#x00148;" ><!--LATIN SMALL LETTER N WITH CARON -->
+<!ENTITY ncedil "&#x00146;" ><!--LATIN SMALL LETTER N WITH CEDILLA -->
+<!ENTITY ncong "&#x02247;" ><!--NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO -->
+<!ENTITY ncongdot "&#x02A6D;&#x00338;" ><!--CONGRUENT WITH DOT ABOVE with slash -->
+<!ENTITY ncup "&#x02A42;" ><!--UNION WITH OVERBAR -->
+<!ENTITY ncy "&#x0043D;" ><!--CYRILLIC SMALL LETTER EN -->
+<!ENTITY ndash "&#x02013;" ><!--EN DASH -->
+<!ENTITY ne "&#x02260;" ><!--NOT EQUAL TO -->
+<!ENTITY neArr "&#x021D7;" ><!--NORTH EAST DOUBLE ARROW -->
+<!ENTITY nearhk "&#x02924;" ><!--NORTH EAST ARROW WITH HOOK -->
+<!ENTITY nearr "&#x02197;" ><!--NORTH EAST ARROW -->
+<!ENTITY nearrow "&#x02197;" ><!--NORTH EAST ARROW -->
+<!ENTITY nedot "&#x02250;&#x00338;" ><!--APPROACHES THE LIMIT with slash -->
+<!ENTITY nequiv "&#x02262;" ><!--NOT IDENTICAL TO -->
+<!ENTITY nesear "&#x02928;" ><!--NORTH EAST ARROW AND SOUTH EAST ARROW -->
+<!ENTITY nesim "&#x02242;&#x00338;" ><!--MINUS TILDE with slash -->
+<!ENTITY nexist "&#x02204;" ><!--THERE DOES NOT EXIST -->
+<!ENTITY nexists "&#x02204;" ><!--THERE DOES NOT EXIST -->
+<!ENTITY nfr "&#x1D52B;" ><!--MATHEMATICAL FRAKTUR SMALL N -->
+<!ENTITY ngE "&#x02267;&#x00338;" ><!--GREATER-THAN OVER EQUAL TO with slash -->
+<!ENTITY nge "&#x02271;" ><!--NEITHER GREATER-THAN NOR EQUAL TO -->
+<!ENTITY ngeq "&#x02271;" ><!--NEITHER GREATER-THAN NOR EQUAL TO -->
+<!ENTITY ngeqq "&#x02267;&#x00338;" ><!--GREATER-THAN OVER EQUAL TO with slash -->
+<!ENTITY ngeqslant "&#x02A7E;&#x00338;" ><!--GREATER-THAN OR SLANTED EQUAL TO with slash -->
+<!ENTITY nges "&#x02A7E;&#x00338;" ><!--GREATER-THAN OR SLANTED EQUAL TO with slash -->
+<!ENTITY ngsim "&#x02275;" ><!--NEITHER GREATER-THAN NOR EQUIVALENT TO -->
+<!ENTITY ngt "&#x0226F;" ><!--NOT GREATER-THAN -->
+<!ENTITY ngtr "&#x0226F;" ><!--NOT GREATER-THAN -->
+<!ENTITY nhArr "&#x021CE;" ><!--LEFT RIGHT DOUBLE ARROW WITH STROKE -->
+<!ENTITY nharr "&#x021AE;" ><!--LEFT RIGHT ARROW WITH STROKE -->
+<!ENTITY nhpar "&#x02AF2;" ><!--PARALLEL WITH HORIZONTAL STROKE -->
+<!ENTITY ni "&#x0220B;" ><!--CONTAINS AS MEMBER -->
+<!ENTITY nis "&#x022FC;" ><!--SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE -->
+<!ENTITY nisd "&#x022FA;" ><!--CONTAINS WITH LONG HORIZONTAL STROKE -->
+<!ENTITY niv "&#x0220B;" ><!--CONTAINS AS MEMBER -->
+<!ENTITY njcy "&#x0045A;" ><!--CYRILLIC SMALL LETTER NJE -->
+<!ENTITY nlArr "&#x021CD;" ><!--LEFTWARDS DOUBLE ARROW WITH STROKE -->
+<!ENTITY nlE "&#x02266;&#x00338;" ><!--LESS-THAN OVER EQUAL TO with slash -->
+<!ENTITY nlarr "&#x0219A;" ><!--LEFTWARDS ARROW WITH STROKE -->
+<!ENTITY nldr "&#x02025;" ><!--TWO DOT LEADER -->
+<!ENTITY nle "&#x02270;" ><!--NEITHER LESS-THAN NOR EQUAL TO -->
+<!ENTITY nleftarrow "&#x0219A;" ><!--LEFTWARDS ARROW WITH STROKE -->
+<!ENTITY nleftrightarrow "&#x021AE;" ><!--LEFT RIGHT ARROW WITH STROKE -->
+<!ENTITY nleq "&#x02270;" ><!--NEITHER LESS-THAN NOR EQUAL TO -->
+<!ENTITY nleqq "&#x02266;&#x00338;" ><!--LESS-THAN OVER EQUAL TO with slash -->
+<!ENTITY nleqslant "&#x02A7D;&#x00338;" ><!--LESS-THAN OR SLANTED EQUAL TO with slash -->
+<!ENTITY nles "&#x02A7D;&#x00338;" ><!--LESS-THAN OR SLANTED EQUAL TO with slash -->
+<!ENTITY nless "&#x0226E;" ><!--NOT LESS-THAN -->
+<!ENTITY nlsim "&#x02274;" ><!--NEITHER LESS-THAN NOR EQUIVALENT TO -->
+<!ENTITY nlt "&#x0226E;" ><!--NOT LESS-THAN -->
+<!ENTITY nltri "&#x022EA;" ><!--NOT NORMAL SUBGROUP OF -->
+<!ENTITY nltrie "&#x022EC;" ><!--NOT NORMAL SUBGROUP OF OR EQUAL TO -->
+<!ENTITY nmid "&#x02224;" ><!--DOES NOT DIVIDE -->
+<!ENTITY nopf "&#x1D55F;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL N -->
+<!ENTITY not "&#x000AC;" ><!--NOT SIGN -->
+<!ENTITY notin "&#x02209;" ><!--NOT AN ELEMENT OF -->
+<!ENTITY notinE "&#x022F9;&#x00338;" ><!--ELEMENT OF WITH TWO HORIZONTAL STROKES with slash -->
+<!ENTITY notindot "&#x022F5;&#x00338;" ><!--ELEMENT OF WITH DOT ABOVE with slash -->
+<!ENTITY notinva "&#x02209;" ><!--NOT AN ELEMENT OF -->
+<!ENTITY notinvb "&#x022F7;" ><!--SMALL ELEMENT OF WITH OVERBAR -->
+<!ENTITY notinvc "&#x022F6;" ><!--ELEMENT OF WITH OVERBAR -->
+<!ENTITY notni "&#x0220C;" ><!--DOES NOT CONTAIN AS MEMBER -->
+<!ENTITY notniva "&#x0220C;" ><!--DOES NOT CONTAIN AS MEMBER -->
+<!ENTITY notnivb "&#x022FE;" ><!--SMALL CONTAINS WITH OVERBAR -->
+<!ENTITY notnivc "&#x022FD;" ><!--CONTAINS WITH OVERBAR -->
+<!ENTITY npar "&#x02226;" ><!--NOT PARALLEL TO -->
+<!ENTITY nparallel "&#x02226;" ><!--NOT PARALLEL TO -->
+<!ENTITY nparsl "&#x02AFD;&#x020E5;" ><!--DOUBLE SOLIDUS OPERATOR with reverse slash -->
+<!ENTITY npart "&#x02202;&#x00338;" ><!--PARTIAL DIFFERENTIAL with slash -->
+<!ENTITY npolint "&#x02A14;" ><!--LINE INTEGRATION NOT INCLUDING THE POLE -->
+<!ENTITY npr "&#x02280;" ><!--DOES NOT PRECEDE -->
+<!ENTITY nprcue "&#x022E0;" ><!--DOES NOT PRECEDE OR EQUAL -->
+<!ENTITY npre "&#x02AAF;&#x00338;" ><!--PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash -->
+<!ENTITY nprec "&#x02280;" ><!--DOES NOT PRECEDE -->
+<!ENTITY npreceq "&#x02AAF;&#x00338;" ><!--PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash -->
+<!ENTITY nrArr "&#x021CF;" ><!--RIGHTWARDS DOUBLE ARROW WITH STROKE -->
+<!ENTITY nrarr "&#x0219B;" ><!--RIGHTWARDS ARROW WITH STROKE -->
+<!ENTITY nrarrc "&#x02933;&#x00338;" ><!--WAVE ARROW POINTING DIRECTLY RIGHT with slash -->
+<!ENTITY nrarrw "&#x0219D;&#x00338;" ><!--RIGHTWARDS WAVE ARROW with slash -->
+<!ENTITY nrightarrow "&#x0219B;" ><!--RIGHTWARDS ARROW WITH STROKE -->
+<!ENTITY nrtri "&#x022EB;" ><!--DOES NOT CONTAIN AS NORMAL SUBGROUP -->
+<!ENTITY nrtrie "&#x022ED;" ><!--DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL -->
+<!ENTITY nsc "&#x02281;" ><!--DOES NOT SUCCEED -->
+<!ENTITY nsccue "&#x022E1;" ><!--DOES NOT SUCCEED OR EQUAL -->
+<!ENTITY nsce "&#x02AB0;&#x00338;" ><!--SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash -->
+<!ENTITY nscr "&#x1D4C3;" ><!--MATHEMATICAL SCRIPT SMALL N -->
+<!ENTITY nshortmid "&#x02224;" ><!--DOES NOT DIVIDE -->
+<!ENTITY nshortparallel "&#x02226;" ><!--NOT PARALLEL TO -->
+<!ENTITY nsim "&#x02241;" ><!--NOT TILDE -->
+<!ENTITY nsime "&#x02244;" ><!--NOT ASYMPTOTICALLY EQUAL TO -->
+<!ENTITY nsimeq "&#x02244;" ><!--NOT ASYMPTOTICALLY EQUAL TO -->
+<!ENTITY nsmid "&#x02224;" ><!--DOES NOT DIVIDE -->
+<!ENTITY nspar "&#x02226;" ><!--NOT PARALLEL TO -->
+<!ENTITY nsqsube "&#x022E2;" ><!--NOT SQUARE IMAGE OF OR EQUAL TO -->
+<!ENTITY nsqsupe "&#x022E3;" ><!--NOT SQUARE ORIGINAL OF OR EQUAL TO -->
+<!ENTITY nsub "&#x02284;" ><!--NOT A SUBSET OF -->
+<!ENTITY nsubE "&#x02AC5;&#x00338;" ><!--SUBSET OF ABOVE EQUALS SIGN with slash -->
+<!ENTITY nsube "&#x02288;" ><!--NEITHER A SUBSET OF NOR EQUAL TO -->
+<!ENTITY nsubset "&#x02282;&#x020D2;" ><!--SUBSET OF with vertical line -->
+<!ENTITY nsubseteq "&#x02288;" ><!--NEITHER A SUBSET OF NOR EQUAL TO -->
+<!ENTITY nsubseteqq "&#x02AC5;&#x00338;" ><!--SUBSET OF ABOVE EQUALS SIGN with slash -->
+<!ENTITY nsucc "&#x02281;" ><!--DOES NOT SUCCEED -->
+<!ENTITY nsucceq "&#x02AB0;&#x00338;" ><!--SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash -->
+<!ENTITY nsup "&#x02285;" ><!--NOT A SUPERSET OF -->
+<!ENTITY nsupE "&#x02AC6;&#x00338;" ><!--SUPERSET OF ABOVE EQUALS SIGN with slash -->
+<!ENTITY nsupe "&#x02289;" ><!--NEITHER A SUPERSET OF NOR EQUAL TO -->
+<!ENTITY nsupset "&#x02283;&#x020D2;" ><!--SUPERSET OF with vertical line -->
+<!ENTITY nsupseteq "&#x02289;" ><!--NEITHER A SUPERSET OF NOR EQUAL TO -->
+<!ENTITY nsupseteqq "&#x02AC6;&#x00338;" ><!--SUPERSET OF ABOVE EQUALS SIGN with slash -->
+<!ENTITY ntgl "&#x02279;" ><!--NEITHER GREATER-THAN NOR LESS-THAN -->
+<!ENTITY ntilde "&#x000F1;" ><!--LATIN SMALL LETTER N WITH TILDE -->
+<!ENTITY ntlg "&#x02278;" ><!--NEITHER LESS-THAN NOR GREATER-THAN -->
+<!ENTITY ntriangleleft "&#x022EA;" ><!--NOT NORMAL SUBGROUP OF -->
+<!ENTITY ntrianglelefteq "&#x022EC;" ><!--NOT NORMAL SUBGROUP OF OR EQUAL TO -->
+<!ENTITY ntriangleright "&#x022EB;" ><!--DOES NOT CONTAIN AS NORMAL SUBGROUP -->
+<!ENTITY ntrianglerighteq "&#x022ED;" ><!--DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL -->
+<!ENTITY nu "&#x003BD;" ><!--GREEK SMALL LETTER NU -->
+<!ENTITY num "&#x00023;" ><!--NUMBER SIGN -->
+<!ENTITY numero "&#x02116;" ><!--NUMERO SIGN -->
+<!ENTITY numsp "&#x02007;" ><!--FIGURE SPACE -->
+<!ENTITY nvDash "&#x022AD;" ><!--NOT TRUE -->
+<!ENTITY nvHarr "&#x02904;" ><!--LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE -->
+<!ENTITY nvap "&#x0224D;&#x020D2;" ><!--EQUIVALENT TO with vertical line -->
+<!ENTITY nvdash "&#x022AC;" ><!--DOES NOT PROVE -->
+<!ENTITY nvge "&#x02265;&#x020D2;" ><!--GREATER-THAN OR EQUAL TO with vertical line -->
+<!ENTITY nvgt "&#x0003E;&#x020D2;" ><!--GREATER-THAN SIGN with vertical line -->
+<!ENTITY nvinfin "&#x029DE;" ><!--INFINITY NEGATED WITH VERTICAL BAR -->
+<!ENTITY nvlArr "&#x02902;" ><!--LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE -->
+<!ENTITY nvle "&#x02264;&#x020D2;" ><!--LESS-THAN OR EQUAL TO with vertical line -->
+<!ENTITY nvlt "&#38;#x0003C;&#x020D2;" ><!--LESS-THAN SIGN with vertical line -->
+<!ENTITY nvltrie "&#x022B4;&#x020D2;" ><!--NORMAL SUBGROUP OF OR EQUAL TO with vertical line -->
+<!ENTITY nvrArr "&#x02903;" ><!--RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE -->
+<!ENTITY nvrtrie "&#x022B5;&#x020D2;" ><!--CONTAINS AS NORMAL SUBGROUP OR EQUAL TO with vertical line -->
+<!ENTITY nvsim "&#x0223C;&#x020D2;" ><!--TILDE OPERATOR with vertical line -->
+<!ENTITY nwArr "&#x021D6;" ><!--NORTH WEST DOUBLE ARROW -->
+<!ENTITY nwarhk "&#x02923;" ><!--NORTH WEST ARROW WITH HOOK -->
+<!ENTITY nwarr "&#x02196;" ><!--NORTH WEST ARROW -->
+<!ENTITY nwarrow "&#x02196;" ><!--NORTH WEST ARROW -->
+<!ENTITY nwnear "&#x02927;" ><!--NORTH WEST ARROW AND NORTH EAST ARROW -->
+<!ENTITY oS "&#x024C8;" ><!--CIRCLED LATIN CAPITAL LETTER S -->
+<!ENTITY oacute "&#x000F3;" ><!--LATIN SMALL LETTER O WITH ACUTE -->
+<!ENTITY oast "&#x0229B;" ><!--CIRCLED ASTERISK OPERATOR -->
+<!ENTITY ocir "&#x0229A;" ><!--CIRCLED RING OPERATOR -->
+<!ENTITY ocirc "&#x000F4;" ><!--LATIN SMALL LETTER O WITH CIRCUMFLEX -->
+<!ENTITY ocy "&#x0043E;" ><!--CYRILLIC SMALL LETTER O -->
+<!ENTITY odash "&#x0229D;" ><!--CIRCLED DASH -->
+<!ENTITY odblac "&#x00151;" ><!--LATIN SMALL LETTER O WITH DOUBLE ACUTE -->
+<!ENTITY odiv "&#x02A38;" ><!--CIRCLED DIVISION SIGN -->
+<!ENTITY odot "&#x02299;" ><!--CIRCLED DOT OPERATOR -->
+<!ENTITY odsold "&#x029BC;" ><!--CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN -->
+<!ENTITY oelig "&#x00153;" ><!--LATIN SMALL LIGATURE OE -->
+<!ENTITY ofcir "&#x029BF;" ><!--CIRCLED BULLET -->
+<!ENTITY ofr "&#x1D52C;" ><!--MATHEMATICAL FRAKTUR SMALL O -->
+<!ENTITY ogon "&#x002DB;" ><!--OGONEK -->
+<!ENTITY ograve "&#x000F2;" ><!--LATIN SMALL LETTER O WITH GRAVE -->
+<!ENTITY ogt "&#x029C1;" ><!--CIRCLED GREATER-THAN -->
+<!ENTITY ohbar "&#x029B5;" ><!--CIRCLE WITH HORIZONTAL BAR -->
+<!ENTITY ohm "&#x003A9;" ><!--GREEK CAPITAL LETTER OMEGA -->
+<!ENTITY oint "&#x0222E;" ><!--CONTOUR INTEGRAL -->
+<!ENTITY olarr "&#x021BA;" ><!--ANTICLOCKWISE OPEN CIRCLE ARROW -->
+<!ENTITY olcir "&#x029BE;" ><!--CIRCLED WHITE BULLET -->
+<!ENTITY olcross "&#x029BB;" ><!--CIRCLE WITH SUPERIMPOSED X -->
+<!ENTITY oline "&#x0203E;" ><!--OVERLINE -->
+<!ENTITY olt "&#x029C0;" ><!--CIRCLED LESS-THAN -->
+<!ENTITY omacr "&#x0014D;" ><!--LATIN SMALL LETTER O WITH MACRON -->
+<!ENTITY omega "&#x003C9;" ><!--GREEK SMALL LETTER OMEGA -->
+<!ENTITY omicron "&#x003BF;" ><!--GREEK SMALL LETTER OMICRON -->
+<!ENTITY omid "&#x029B6;" ><!--CIRCLED VERTICAL BAR -->
+<!ENTITY ominus "&#x02296;" ><!--CIRCLED MINUS -->
+<!ENTITY oopf "&#x1D560;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL O -->
+<!ENTITY opar "&#x029B7;" ><!--CIRCLED PARALLEL -->
+<!ENTITY operp "&#x029B9;" ><!--CIRCLED PERPENDICULAR -->
+<!ENTITY oplus "&#x02295;" ><!--CIRCLED PLUS -->
+<!ENTITY or "&#x02228;" ><!--LOGICAL OR -->
+<!ENTITY orarr "&#x021BB;" ><!--CLOCKWISE OPEN CIRCLE ARROW -->
+<!ENTITY ord "&#x02A5D;" ><!--LOGICAL OR WITH HORIZONTAL DASH -->
+<!ENTITY order "&#x02134;" ><!--SCRIPT SMALL O -->
+<!ENTITY orderof "&#x02134;" ><!--SCRIPT SMALL O -->
+<!ENTITY ordf "&#x000AA;" ><!--FEMININE ORDINAL INDICATOR -->
+<!ENTITY ordm "&#x000BA;" ><!--MASCULINE ORDINAL INDICATOR -->
+<!ENTITY origof "&#x022B6;" ><!--ORIGINAL OF -->
+<!ENTITY oror "&#x02A56;" ><!--TWO INTERSECTING LOGICAL OR -->
+<!ENTITY orslope "&#x02A57;" ><!--SLOPING LARGE OR -->
+<!ENTITY orv "&#x02A5B;" ><!--LOGICAL OR WITH MIDDLE STEM -->
+<!ENTITY oscr "&#x02134;" ><!--SCRIPT SMALL O -->
+<!ENTITY oslash "&#x000F8;" ><!--LATIN SMALL LETTER O WITH STROKE -->
+<!ENTITY osol "&#x02298;" ><!--CIRCLED DIVISION SLASH -->
+<!ENTITY otilde "&#x000F5;" ><!--LATIN SMALL LETTER O WITH TILDE -->
+<!ENTITY otimes "&#x02297;" ><!--CIRCLED TIMES -->
+<!ENTITY otimesas "&#x02A36;" ><!--CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT -->
+<!ENTITY ouml "&#x000F6;" ><!--LATIN SMALL LETTER O WITH DIAERESIS -->
+<!ENTITY ovbar "&#x0233D;" ><!--APL FUNCTIONAL SYMBOL CIRCLE STILE -->
+<!ENTITY par "&#x02225;" ><!--PARALLEL TO -->
+<!ENTITY para "&#x000B6;" ><!--PILCROW SIGN -->
+<!ENTITY parallel "&#x02225;" ><!--PARALLEL TO -->
+<!ENTITY parsim "&#x02AF3;" ><!--PARALLEL WITH TILDE OPERATOR -->
+<!ENTITY parsl "&#x02AFD;" ><!--DOUBLE SOLIDUS OPERATOR -->
+<!ENTITY part "&#x02202;" ><!--PARTIAL DIFFERENTIAL -->
+<!ENTITY pcy "&#x0043F;" ><!--CYRILLIC SMALL LETTER PE -->
+<!ENTITY percnt "&#x00025;" ><!--PERCENT SIGN -->
+<!ENTITY period "&#x0002E;" ><!--FULL STOP -->
+<!ENTITY permil "&#x02030;" ><!--PER MILLE SIGN -->
+<!ENTITY perp "&#x022A5;" ><!--UP TACK -->
+<!ENTITY pertenk "&#x02031;" ><!--PER TEN THOUSAND SIGN -->
+<!ENTITY pfr "&#x1D52D;" ><!--MATHEMATICAL FRAKTUR SMALL P -->
+<!ENTITY phi "&#x003C6;" ><!--GREEK SMALL LETTER PHI -->
+<!ENTITY phiv "&#x003D5;" ><!--GREEK PHI SYMBOL -->
+<!ENTITY phmmat "&#x02133;" ><!--SCRIPT CAPITAL M -->
+<!ENTITY phone "&#x0260E;" ><!--BLACK TELEPHONE -->
+<!ENTITY pi "&#x003C0;" ><!--GREEK SMALL LETTER PI -->
+<!ENTITY pitchfork "&#x022D4;" ><!--PITCHFORK -->
+<!ENTITY piv "&#x003D6;" ><!--GREEK PI SYMBOL -->
+<!ENTITY planck "&#x0210F;" ><!--PLANCK CONSTANT OVER TWO PI -->
+<!ENTITY planckh "&#x0210E;" ><!--PLANCK CONSTANT -->
+<!ENTITY plankv "&#x0210F;" ><!--PLANCK CONSTANT OVER TWO PI -->
+<!ENTITY plus "&#x0002B;" ><!--PLUS SIGN -->
+<!ENTITY plusacir "&#x02A23;" ><!--PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE -->
+<!ENTITY plusb "&#x0229E;" ><!--SQUARED PLUS -->
+<!ENTITY pluscir "&#x02A22;" ><!--PLUS SIGN WITH SMALL CIRCLE ABOVE -->
+<!ENTITY plusdo "&#x02214;" ><!--DOT PLUS -->
+<!ENTITY plusdu "&#x02A25;" ><!--PLUS SIGN WITH DOT BELOW -->
+<!ENTITY pluse "&#x02A72;" ><!--PLUS SIGN ABOVE EQUALS SIGN -->
+<!ENTITY plusmn "&#x000B1;" ><!--PLUS-MINUS SIGN -->
+<!ENTITY plussim "&#x02A26;" ><!--PLUS SIGN WITH TILDE BELOW -->
+<!ENTITY plustwo "&#x02A27;" ><!--PLUS SIGN WITH SUBSCRIPT TWO -->
+<!ENTITY pm "&#x000B1;" ><!--PLUS-MINUS SIGN -->
+<!ENTITY pointint "&#x02A15;" ><!--INTEGRAL AROUND A POINT OPERATOR -->
+<!ENTITY popf "&#x1D561;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL P -->
+<!ENTITY pound "&#x000A3;" ><!--POUND SIGN -->
+<!ENTITY pr "&#x0227A;" ><!--PRECEDES -->
+<!ENTITY prE "&#x02AB3;" ><!--PRECEDES ABOVE EQUALS SIGN -->
+<!ENTITY prap "&#x02AB7;" ><!--PRECEDES ABOVE ALMOST EQUAL TO -->
+<!ENTITY prcue "&#x0227C;" ><!--PRECEDES OR EQUAL TO -->
+<!ENTITY pre "&#x02AAF;" ><!--PRECEDES ABOVE SINGLE-LINE EQUALS SIGN -->
+<!ENTITY prec "&#x0227A;" ><!--PRECEDES -->
+<!ENTITY precapprox "&#x02AB7;" ><!--PRECEDES ABOVE ALMOST EQUAL TO -->
+<!ENTITY preccurlyeq "&#x0227C;" ><!--PRECEDES OR EQUAL TO -->
+<!ENTITY preceq "&#x02AAF;" ><!--PRECEDES ABOVE SINGLE-LINE EQUALS SIGN -->
+<!ENTITY precnapprox "&#x02AB9;" ><!--PRECEDES ABOVE NOT ALMOST EQUAL TO -->
+<!ENTITY precneqq "&#x02AB5;" ><!--PRECEDES ABOVE NOT EQUAL TO -->
+<!ENTITY precnsim "&#x022E8;" ><!--PRECEDES BUT NOT EQUIVALENT TO -->
+<!ENTITY precsim "&#x0227E;" ><!--PRECEDES OR EQUIVALENT TO -->
+<!ENTITY prime "&#x02032;" ><!--PRIME -->
+<!ENTITY primes "&#x02119;" ><!--DOUBLE-STRUCK CAPITAL P -->
+<!ENTITY prnE "&#x02AB5;" ><!--PRECEDES ABOVE NOT EQUAL TO -->
+<!ENTITY prnap "&#x02AB9;" ><!--PRECEDES ABOVE NOT ALMOST EQUAL TO -->
+<!ENTITY prnsim "&#x022E8;" ><!--PRECEDES BUT NOT EQUIVALENT TO -->
+<!ENTITY prod "&#x0220F;" ><!--N-ARY PRODUCT -->
+<!ENTITY profalar "&#x0232E;" ><!--ALL AROUND-PROFILE -->
+<!ENTITY profline "&#x02312;" ><!--ARC -->
+<!ENTITY profsurf "&#x02313;" ><!--SEGMENT -->
+<!ENTITY prop "&#x0221D;" ><!--PROPORTIONAL TO -->
+<!ENTITY propto "&#x0221D;" ><!--PROPORTIONAL TO -->
+<!ENTITY prsim "&#x0227E;" ><!--PRECEDES OR EQUIVALENT TO -->
+<!ENTITY prurel "&#x022B0;" ><!--PRECEDES UNDER RELATION -->
+<!ENTITY pscr "&#x1D4C5;" ><!--MATHEMATICAL SCRIPT SMALL P -->
+<!ENTITY psi "&#x003C8;" ><!--GREEK SMALL LETTER PSI -->
+<!ENTITY puncsp "&#x02008;" ><!--PUNCTUATION SPACE -->
+<!ENTITY qfr "&#x1D52E;" ><!--MATHEMATICAL FRAKTUR SMALL Q -->
+<!ENTITY qint "&#x02A0C;" ><!--QUADRUPLE INTEGRAL OPERATOR -->
+<!ENTITY qopf "&#x1D562;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL Q -->
+<!ENTITY qprime "&#x02057;" ><!--QUADRUPLE PRIME -->
+<!ENTITY qscr "&#x1D4C6;" ><!--MATHEMATICAL SCRIPT SMALL Q -->
+<!ENTITY quaternions "&#x0210D;" ><!--DOUBLE-STRUCK CAPITAL H -->
+<!ENTITY quatint "&#x02A16;" ><!--QUATERNION INTEGRAL OPERATOR -->
+<!ENTITY quest "&#x0003F;" ><!--QUESTION MARK -->
+<!ENTITY questeq "&#x0225F;" ><!--QUESTIONED EQUAL TO -->
+<!ENTITY quot "&#x00022;" ><!--QUOTATION MARK -->
+<!ENTITY rAarr "&#x021DB;" ><!--RIGHTWARDS TRIPLE ARROW -->
+<!ENTITY rArr "&#x021D2;" ><!--RIGHTWARDS DOUBLE ARROW -->
+<!ENTITY rAtail "&#x0291C;" ><!--RIGHTWARDS DOUBLE ARROW-TAIL -->
+<!ENTITY rBarr "&#x0290F;" ><!--RIGHTWARDS TRIPLE DASH ARROW -->
+<!ENTITY rHar "&#x02964;" ><!--RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN -->
+<!ENTITY race "&#x0223D;&#x00331;" ><!--REVERSED TILDE with underline -->
+<!ENTITY racute "&#x00155;" ><!--LATIN SMALL LETTER R WITH ACUTE -->
+<!ENTITY radic "&#x0221A;" ><!--SQUARE ROOT -->
+<!ENTITY raemptyv "&#x029B3;" ><!--EMPTY SET WITH RIGHT ARROW ABOVE -->
+<!ENTITY rang "&#x027E9;" ><!--MATHEMATICAL RIGHT ANGLE BRACKET -->
+<!ENTITY rangd "&#x02992;" ><!--RIGHT ANGLE BRACKET WITH DOT -->
+<!ENTITY range "&#x029A5;" ><!--REVERSED ANGLE WITH UNDERBAR -->
+<!ENTITY rangle "&#x027E9;" ><!--MATHEMATICAL RIGHT ANGLE BRACKET -->
+<!ENTITY raquo "&#x000BB;" ><!--RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK -->
+<!ENTITY rarr "&#x02192;" ><!--RIGHTWARDS ARROW -->
+<!ENTITY rarrap "&#x02975;" ><!--RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO -->
+<!ENTITY rarrb "&#x021E5;" ><!--RIGHTWARDS ARROW TO BAR -->
+<!ENTITY rarrbfs "&#x02920;" ><!--RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND -->
+<!ENTITY rarrc "&#x02933;" ><!--WAVE ARROW POINTING DIRECTLY RIGHT -->
+<!ENTITY rarrfs "&#x0291E;" ><!--RIGHTWARDS ARROW TO BLACK DIAMOND -->
+<!ENTITY rarrhk "&#x021AA;" ><!--RIGHTWARDS ARROW WITH HOOK -->
+<!ENTITY rarrlp "&#x021AC;" ><!--RIGHTWARDS ARROW WITH LOOP -->
+<!ENTITY rarrpl "&#x02945;" ><!--RIGHTWARDS ARROW WITH PLUS BELOW -->
+<!ENTITY rarrsim "&#x02974;" ><!--RIGHTWARDS ARROW ABOVE TILDE OPERATOR -->
+<!ENTITY rarrtl "&#x021A3;" ><!--RIGHTWARDS ARROW WITH TAIL -->
+<!ENTITY rarrw "&#x0219D;" ><!--RIGHTWARDS WAVE ARROW -->
+<!ENTITY ratail "&#x0291A;" ><!--RIGHTWARDS ARROW-TAIL -->
+<!ENTITY ratio "&#x02236;" ><!--RATIO -->
+<!ENTITY rationals "&#x0211A;" ><!--DOUBLE-STRUCK CAPITAL Q -->
+<!ENTITY rbarr "&#x0290D;" ><!--RIGHTWARDS DOUBLE DASH ARROW -->
+<!ENTITY rbbrk "&#x02773;" ><!--LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT -->
+<!ENTITY rbrace "&#x0007D;" ><!--RIGHT CURLY BRACKET -->
+<!ENTITY rbrack "&#x0005D;" ><!--RIGHT SQUARE BRACKET -->
+<!ENTITY rbrke "&#x0298C;" ><!--RIGHT SQUARE BRACKET WITH UNDERBAR -->
+<!ENTITY rbrksld "&#x0298E;" ><!--RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER -->
+<!ENTITY rbrkslu "&#x02990;" ><!--RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER -->
+<!ENTITY rcaron "&#x00159;" ><!--LATIN SMALL LETTER R WITH CARON -->
+<!ENTITY rcedil "&#x00157;" ><!--LATIN SMALL LETTER R WITH CEDILLA -->
+<!ENTITY rceil "&#x02309;" ><!--RIGHT CEILING -->
+<!ENTITY rcub "&#x0007D;" ><!--RIGHT CURLY BRACKET -->
+<!ENTITY rcy "&#x00440;" ><!--CYRILLIC SMALL LETTER ER -->
+<!ENTITY rdca "&#x02937;" ><!--ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS -->
+<!ENTITY rdldhar "&#x02969;" ><!--RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN -->
+<!ENTITY rdquo "&#x0201D;" ><!--RIGHT DOUBLE QUOTATION MARK -->
+<!ENTITY rdquor "&#x0201D;" ><!--RIGHT DOUBLE QUOTATION MARK -->
+<!ENTITY rdsh "&#x021B3;" ><!--DOWNWARDS ARROW WITH TIP RIGHTWARDS -->
+<!ENTITY real "&#x0211C;" ><!--BLACK-LETTER CAPITAL R -->
+<!ENTITY realine "&#x0211B;" ><!--SCRIPT CAPITAL R -->
+<!ENTITY realpart "&#x0211C;" ><!--BLACK-LETTER CAPITAL R -->
+<!ENTITY reals "&#x0211D;" ><!--DOUBLE-STRUCK CAPITAL R -->
+<!ENTITY rect "&#x025AD;" ><!--WHITE RECTANGLE -->
+<!ENTITY reg "&#x000AE;" ><!--REGISTERED SIGN -->
+<!ENTITY rfisht "&#x0297D;" ><!--RIGHT FISH TAIL -->
+<!ENTITY rfloor "&#x0230B;" ><!--RIGHT FLOOR -->
+<!ENTITY rfr "&#x1D52F;" ><!--MATHEMATICAL FRAKTUR SMALL R -->
+<!ENTITY rhard "&#x021C1;" ><!--RIGHTWARDS HARPOON WITH BARB DOWNWARDS -->
+<!ENTITY rharu "&#x021C0;" ><!--RIGHTWARDS HARPOON WITH BARB UPWARDS -->
+<!ENTITY rharul "&#x0296C;" ><!--RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH -->
+<!ENTITY rho "&#x003C1;" ><!--GREEK SMALL LETTER RHO -->
+<!ENTITY rhov "&#x003F1;" ><!--GREEK RHO SYMBOL -->
+<!ENTITY rightarrow "&#x02192;" ><!--RIGHTWARDS ARROW -->
+<!ENTITY rightarrowtail "&#x021A3;" ><!--RIGHTWARDS ARROW WITH TAIL -->
+<!ENTITY rightharpoondown "&#x021C1;" ><!--RIGHTWARDS HARPOON WITH BARB DOWNWARDS -->
+<!ENTITY rightharpoonup "&#x021C0;" ><!--RIGHTWARDS HARPOON WITH BARB UPWARDS -->
+<!ENTITY rightleftarrows "&#x021C4;" ><!--RIGHTWARDS ARROW OVER LEFTWARDS ARROW -->
+<!ENTITY rightleftharpoons "&#x021CC;" ><!--RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON -->
+<!ENTITY rightrightarrows "&#x021C9;" ><!--RIGHTWARDS PAIRED ARROWS -->
+<!ENTITY rightsquigarrow "&#x0219D;" ><!--RIGHTWARDS WAVE ARROW -->
+<!ENTITY rightthreetimes "&#x022CC;" ><!--RIGHT SEMIDIRECT PRODUCT -->
+<!ENTITY ring "&#x002DA;" ><!--RING ABOVE -->
+<!ENTITY risingdotseq "&#x02253;" ><!--IMAGE OF OR APPROXIMATELY EQUAL TO -->
+<!ENTITY rlarr "&#x021C4;" ><!--RIGHTWARDS ARROW OVER LEFTWARDS ARROW -->
+<!ENTITY rlhar "&#x021CC;" ><!--RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON -->
+<!ENTITY rlm "&#x0200F;" ><!--RIGHT-TO-LEFT MARK -->
+<!ENTITY rmoust "&#x023B1;" ><!--UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION -->
+<!ENTITY rmoustache "&#x023B1;" ><!--UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION -->
+<!ENTITY rnmid "&#x02AEE;" ><!--DOES NOT DIVIDE WITH REVERSED NEGATION SLASH -->
+<!ENTITY roang "&#x027ED;" ><!--MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET -->
+<!ENTITY roarr "&#x021FE;" ><!--RIGHTWARDS OPEN-HEADED ARROW -->
+<!ENTITY robrk "&#x027E7;" ><!--MATHEMATICAL RIGHT WHITE SQUARE BRACKET -->
+<!ENTITY ropar "&#x02986;" ><!--RIGHT WHITE PARENTHESIS -->
+<!ENTITY ropf "&#x1D563;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL R -->
+<!ENTITY roplus "&#x02A2E;" ><!--PLUS SIGN IN RIGHT HALF CIRCLE -->
+<!ENTITY rotimes "&#x02A35;" ><!--MULTIPLICATION SIGN IN RIGHT HALF CIRCLE -->
+<!ENTITY rpar "&#x00029;" ><!--RIGHT PARENTHESIS -->
+<!ENTITY rpargt "&#x02994;" ><!--RIGHT ARC GREATER-THAN BRACKET -->
+<!ENTITY rppolint "&#x02A12;" ><!--LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE -->
+<!ENTITY rrarr "&#x021C9;" ><!--RIGHTWARDS PAIRED ARROWS -->
+<!ENTITY rsaquo "&#x0203A;" ><!--SINGLE RIGHT-POINTING ANGLE QUOTATION MARK -->
+<!ENTITY rscr "&#x1D4C7;" ><!--MATHEMATICAL SCRIPT SMALL R -->
+<!ENTITY rsh "&#x021B1;" ><!--UPWARDS ARROW WITH TIP RIGHTWARDS -->
+<!ENTITY rsqb "&#x0005D;" ><!--RIGHT SQUARE BRACKET -->
+<!ENTITY rsquo "&#x02019;" ><!--RIGHT SINGLE QUOTATION MARK -->
+<!ENTITY rsquor "&#x02019;" ><!--RIGHT SINGLE QUOTATION MARK -->
+<!ENTITY rthree "&#x022CC;" ><!--RIGHT SEMIDIRECT PRODUCT -->
+<!ENTITY rtimes "&#x022CA;" ><!--RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT -->
+<!ENTITY rtri "&#x025B9;" ><!--WHITE RIGHT-POINTING SMALL TRIANGLE -->
+<!ENTITY rtrie "&#x022B5;" ><!--CONTAINS AS NORMAL SUBGROUP OR EQUAL TO -->
+<!ENTITY rtrif "&#x025B8;" ><!--BLACK RIGHT-POINTING SMALL TRIANGLE -->
+<!ENTITY rtriltri "&#x029CE;" ><!--RIGHT TRIANGLE ABOVE LEFT TRIANGLE -->
+<!ENTITY ruluhar "&#x02968;" ><!--RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP -->
+<!ENTITY rx "&#x0211E;" ><!--PRESCRIPTION TAKE -->
+<!ENTITY sacute "&#x0015B;" ><!--LATIN SMALL LETTER S WITH ACUTE -->
+<!ENTITY sbquo "&#x0201A;" ><!--SINGLE LOW-9 QUOTATION MARK -->
+<!ENTITY sc "&#x0227B;" ><!--SUCCEEDS -->
+<!ENTITY scE "&#x02AB4;" ><!--SUCCEEDS ABOVE EQUALS SIGN -->
+<!ENTITY scap "&#x02AB8;" ><!--SUCCEEDS ABOVE ALMOST EQUAL TO -->
+<!ENTITY scaron "&#x00161;" ><!--LATIN SMALL LETTER S WITH CARON -->
+<!ENTITY sccue "&#x0227D;" ><!--SUCCEEDS OR EQUAL TO -->
+<!ENTITY sce "&#x02AB0;" ><!--SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN -->
+<!ENTITY scedil "&#x0015F;" ><!--LATIN SMALL LETTER S WITH CEDILLA -->
+<!ENTITY scirc "&#x0015D;" ><!--LATIN SMALL LETTER S WITH CIRCUMFLEX -->
+<!ENTITY scnE "&#x02AB6;" ><!--SUCCEEDS ABOVE NOT EQUAL TO -->
+<!ENTITY scnap "&#x02ABA;" ><!--SUCCEEDS ABOVE NOT ALMOST EQUAL TO -->
+<!ENTITY scnsim "&#x022E9;" ><!--SUCCEEDS BUT NOT EQUIVALENT TO -->
+<!ENTITY scpolint "&#x02A13;" ><!--LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE -->
+<!ENTITY scsim "&#x0227F;" ><!--SUCCEEDS OR EQUIVALENT TO -->
+<!ENTITY scy "&#x00441;" ><!--CYRILLIC SMALL LETTER ES -->
+<!ENTITY sdot "&#x022C5;" ><!--DOT OPERATOR -->
+<!ENTITY sdotb "&#x022A1;" ><!--SQUARED DOT OPERATOR -->
+<!ENTITY sdote "&#x02A66;" ><!--EQUALS SIGN WITH DOT BELOW -->
+<!ENTITY seArr "&#x021D8;" ><!--SOUTH EAST DOUBLE ARROW -->
+<!ENTITY searhk "&#x02925;" ><!--SOUTH EAST ARROW WITH HOOK -->
+<!ENTITY searr "&#x02198;" ><!--SOUTH EAST ARROW -->
+<!ENTITY searrow "&#x02198;" ><!--SOUTH EAST ARROW -->
+<!ENTITY sect "&#x000A7;" ><!--SECTION SIGN -->
+<!ENTITY semi "&#x0003B;" ><!--SEMICOLON -->
+<!ENTITY seswar "&#x02929;" ><!--SOUTH EAST ARROW AND SOUTH WEST ARROW -->
+<!ENTITY setminus "&#x02216;" ><!--SET MINUS -->
+<!ENTITY setmn "&#x02216;" ><!--SET MINUS -->
+<!ENTITY sext "&#x02736;" ><!--SIX POINTED BLACK STAR -->
+<!ENTITY sfr "&#x1D530;" ><!--MATHEMATICAL FRAKTUR SMALL S -->
+<!ENTITY sfrown "&#x02322;" ><!--FROWN -->
+<!ENTITY sharp "&#x0266F;" ><!--MUSIC SHARP SIGN -->
+<!ENTITY shchcy "&#x00449;" ><!--CYRILLIC SMALL LETTER SHCHA -->
+<!ENTITY shcy "&#x00448;" ><!--CYRILLIC SMALL LETTER SHA -->
+<!ENTITY shortmid "&#x02223;" ><!--DIVIDES -->
+<!ENTITY shortparallel "&#x02225;" ><!--PARALLEL TO -->
+<!ENTITY shy "&#x000AD;" ><!--SOFT HYPHEN -->
+<!ENTITY sigma "&#x003C3;" ><!--GREEK SMALL LETTER SIGMA -->
+<!ENTITY sigmaf "&#x003C2;" ><!--GREEK SMALL LETTER FINAL SIGMA -->
+<!ENTITY sigmav "&#x003C2;" ><!--GREEK SMALL LETTER FINAL SIGMA -->
+<!ENTITY sim "&#x0223C;" ><!--TILDE OPERATOR -->
+<!ENTITY simdot "&#x02A6A;" ><!--TILDE OPERATOR WITH DOT ABOVE -->
+<!ENTITY sime "&#x02243;" ><!--ASYMPTOTICALLY EQUAL TO -->
+<!ENTITY simeq "&#x02243;" ><!--ASYMPTOTICALLY EQUAL TO -->
+<!ENTITY simg "&#x02A9E;" ><!--SIMILAR OR GREATER-THAN -->
+<!ENTITY simgE "&#x02AA0;" ><!--SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN -->
+<!ENTITY siml "&#x02A9D;" ><!--SIMILAR OR LESS-THAN -->
+<!ENTITY simlE "&#x02A9F;" ><!--SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN -->
+<!ENTITY simne "&#x02246;" ><!--APPROXIMATELY BUT NOT ACTUALLY EQUAL TO -->
+<!ENTITY simplus "&#x02A24;" ><!--PLUS SIGN WITH TILDE ABOVE -->
+<!ENTITY simrarr "&#x02972;" ><!--TILDE OPERATOR ABOVE RIGHTWARDS ARROW -->
+<!ENTITY slarr "&#x02190;" ><!--LEFTWARDS ARROW -->
+<!ENTITY smallsetminus "&#x02216;" ><!--SET MINUS -->
+<!ENTITY smashp "&#x02A33;" ><!--SMASH PRODUCT -->
+<!ENTITY smeparsl "&#x029E4;" ><!--EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE -->
+<!ENTITY smid "&#x02223;" ><!--DIVIDES -->
+<!ENTITY smile "&#x02323;" ><!--SMILE -->
+<!ENTITY smt "&#x02AAA;" ><!--SMALLER THAN -->
+<!ENTITY smte "&#x02AAC;" ><!--SMALLER THAN OR EQUAL TO -->
+<!ENTITY smtes "&#x02AAC;&#x0FE00;" ><!--SMALLER THAN OR slanted EQUAL -->
+<!ENTITY softcy "&#x0044C;" ><!--CYRILLIC SMALL LETTER SOFT SIGN -->
+<!ENTITY sol "&#x0002F;" ><!--SOLIDUS -->
+<!ENTITY solb "&#x029C4;" ><!--SQUARED RISING DIAGONAL SLASH -->
+<!ENTITY solbar "&#x0233F;" ><!--APL FUNCTIONAL SYMBOL SLASH BAR -->
+<!ENTITY sopf "&#x1D564;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL S -->
+<!ENTITY spades "&#x02660;" ><!--BLACK SPADE SUIT -->
+<!ENTITY spadesuit "&#x02660;" ><!--BLACK SPADE SUIT -->
+<!ENTITY spar "&#x02225;" ><!--PARALLEL TO -->
+<!ENTITY sqcap "&#x02293;" ><!--SQUARE CAP -->
+<!ENTITY sqcaps "&#x02293;&#x0FE00;" ><!--SQUARE CAP with serifs -->
+<!ENTITY sqcup "&#x02294;" ><!--SQUARE CUP -->
+<!ENTITY sqcups "&#x02294;&#x0FE00;" ><!--SQUARE CUP with serifs -->
+<!ENTITY sqsub "&#x0228F;" ><!--SQUARE IMAGE OF -->
+<!ENTITY sqsube "&#x02291;" ><!--SQUARE IMAGE OF OR EQUAL TO -->
+<!ENTITY sqsubset "&#x0228F;" ><!--SQUARE IMAGE OF -->
+<!ENTITY sqsubseteq "&#x02291;" ><!--SQUARE IMAGE OF OR EQUAL TO -->
+<!ENTITY sqsup "&#x02290;" ><!--SQUARE ORIGINAL OF -->
+<!ENTITY sqsupe "&#x02292;" ><!--SQUARE ORIGINAL OF OR EQUAL TO -->
+<!ENTITY sqsupset "&#x02290;" ><!--SQUARE ORIGINAL OF -->
+<!ENTITY sqsupseteq "&#x02292;" ><!--SQUARE ORIGINAL OF OR EQUAL TO -->
+<!ENTITY squ "&#x025A1;" ><!--WHITE SQUARE -->
+<!ENTITY square "&#x025A1;" ><!--WHITE SQUARE -->
+<!ENTITY squarf "&#x025AA;" ><!--BLACK SMALL SQUARE -->
+<!ENTITY squf "&#x025AA;" ><!--BLACK SMALL SQUARE -->
+<!ENTITY srarr "&#x02192;" ><!--RIGHTWARDS ARROW -->
+<!ENTITY sscr "&#x1D4C8;" ><!--MATHEMATICAL SCRIPT SMALL S -->
+<!ENTITY ssetmn "&#x02216;" ><!--SET MINUS -->
+<!ENTITY ssmile "&#x02323;" ><!--SMILE -->
+<!ENTITY sstarf "&#x022C6;" ><!--STAR OPERATOR -->
+<!ENTITY star "&#x02606;" ><!--WHITE STAR -->
+<!ENTITY starf "&#x02605;" ><!--BLACK STAR -->
+<!ENTITY straightepsilon "&#x003F5;" ><!--GREEK LUNATE EPSILON SYMBOL -->
+<!ENTITY straightphi "&#x003D5;" ><!--GREEK PHI SYMBOL -->
+<!ENTITY strns "&#x000AF;" ><!--MACRON -->
+<!ENTITY sub "&#x02282;" ><!--SUBSET OF -->
+<!ENTITY subE "&#x02AC5;" ><!--SUBSET OF ABOVE EQUALS SIGN -->
+<!ENTITY subdot "&#x02ABD;" ><!--SUBSET WITH DOT -->
+<!ENTITY sube "&#x02286;" ><!--SUBSET OF OR EQUAL TO -->
+<!ENTITY subedot "&#x02AC3;" ><!--SUBSET OF OR EQUAL TO WITH DOT ABOVE -->
+<!ENTITY submult "&#x02AC1;" ><!--SUBSET WITH MULTIPLICATION SIGN BELOW -->
+<!ENTITY subnE "&#x02ACB;" ><!--SUBSET OF ABOVE NOT EQUAL TO -->
+<!ENTITY subne "&#x0228A;" ><!--SUBSET OF WITH NOT EQUAL TO -->
+<!ENTITY subplus "&#x02ABF;" ><!--SUBSET WITH PLUS SIGN BELOW -->
+<!ENTITY subrarr "&#x02979;" ><!--SUBSET ABOVE RIGHTWARDS ARROW -->
+<!ENTITY subset "&#x02282;" ><!--SUBSET OF -->
+<!ENTITY subseteq "&#x02286;" ><!--SUBSET OF OR EQUAL TO -->
+<!ENTITY subseteqq "&#x02AC5;" ><!--SUBSET OF ABOVE EQUALS SIGN -->
+<!ENTITY subsetneq "&#x0228A;" ><!--SUBSET OF WITH NOT EQUAL TO -->
+<!ENTITY subsetneqq "&#x02ACB;" ><!--SUBSET OF ABOVE NOT EQUAL TO -->
+<!ENTITY subsim "&#x02AC7;" ><!--SUBSET OF ABOVE TILDE OPERATOR -->
+<!ENTITY subsub "&#x02AD5;" ><!--SUBSET ABOVE SUBSET -->
+<!ENTITY subsup "&#x02AD3;" ><!--SUBSET ABOVE SUPERSET -->
+<!ENTITY succ "&#x0227B;" ><!--SUCCEEDS -->
+<!ENTITY succapprox "&#x02AB8;" ><!--SUCCEEDS ABOVE ALMOST EQUAL TO -->
+<!ENTITY succcurlyeq "&#x0227D;" ><!--SUCCEEDS OR EQUAL TO -->
+<!ENTITY succeq "&#x02AB0;" ><!--SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN -->
+<!ENTITY succnapprox "&#x02ABA;" ><!--SUCCEEDS ABOVE NOT ALMOST EQUAL TO -->
+<!ENTITY succneqq "&#x02AB6;" ><!--SUCCEEDS ABOVE NOT EQUAL TO -->
+<!ENTITY succnsim "&#x022E9;" ><!--SUCCEEDS BUT NOT EQUIVALENT TO -->
+<!ENTITY succsim "&#x0227F;" ><!--SUCCEEDS OR EQUIVALENT TO -->
+<!ENTITY sum "&#x02211;" ><!--N-ARY SUMMATION -->
+<!ENTITY sung "&#x0266A;" ><!--EIGHTH NOTE -->
+<!ENTITY sup "&#x02283;" ><!--SUPERSET OF -->
+<!ENTITY sup1 "&#x000B9;" ><!--SUPERSCRIPT ONE -->
+<!ENTITY sup2 "&#x000B2;" ><!--SUPERSCRIPT TWO -->
+<!ENTITY sup3 "&#x000B3;" ><!--SUPERSCRIPT THREE -->
+<!ENTITY supE "&#x02AC6;" ><!--SUPERSET OF ABOVE EQUALS SIGN -->
+<!ENTITY supdot "&#x02ABE;" ><!--SUPERSET WITH DOT -->
+<!ENTITY supdsub "&#x02AD8;" ><!--SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET -->
+<!ENTITY supe "&#x02287;" ><!--SUPERSET OF OR EQUAL TO -->
+<!ENTITY supedot "&#x02AC4;" ><!--SUPERSET OF OR EQUAL TO WITH DOT ABOVE -->
+<!ENTITY suphsol "&#x027C9;" ><!--SUPERSET PRECEDING SOLIDUS -->
+<!ENTITY suphsub "&#x02AD7;" ><!--SUPERSET BESIDE SUBSET -->
+<!ENTITY suplarr "&#x0297B;" ><!--SUPERSET ABOVE LEFTWARDS ARROW -->
+<!ENTITY supmult "&#x02AC2;" ><!--SUPERSET WITH MULTIPLICATION SIGN BELOW -->
+<!ENTITY supnE "&#x02ACC;" ><!--SUPERSET OF ABOVE NOT EQUAL TO -->
+<!ENTITY supne "&#x0228B;" ><!--SUPERSET OF WITH NOT EQUAL TO -->
+<!ENTITY supplus "&#x02AC0;" ><!--SUPERSET WITH PLUS SIGN BELOW -->
+<!ENTITY supset "&#x02283;" ><!--SUPERSET OF -->
+<!ENTITY supseteq "&#x02287;" ><!--SUPERSET OF OR EQUAL TO -->
+<!ENTITY supseteqq "&#x02AC6;" ><!--SUPERSET OF ABOVE EQUALS SIGN -->
+<!ENTITY supsetneq "&#x0228B;" ><!--SUPERSET OF WITH NOT EQUAL TO -->
+<!ENTITY supsetneqq "&#x02ACC;" ><!--SUPERSET OF ABOVE NOT EQUAL TO -->
+<!ENTITY supsim "&#x02AC8;" ><!--SUPERSET OF ABOVE TILDE OPERATOR -->
+<!ENTITY supsub "&#x02AD4;" ><!--SUPERSET ABOVE SUBSET -->
+<!ENTITY supsup "&#x02AD6;" ><!--SUPERSET ABOVE SUPERSET -->
+<!ENTITY swArr "&#x021D9;" ><!--SOUTH WEST DOUBLE ARROW -->
+<!ENTITY swarhk "&#x02926;" ><!--SOUTH WEST ARROW WITH HOOK -->
+<!ENTITY swarr "&#x02199;" ><!--SOUTH WEST ARROW -->
+<!ENTITY swarrow "&#x02199;" ><!--SOUTH WEST ARROW -->
+<!ENTITY swnwar "&#x0292A;" ><!--SOUTH WEST ARROW AND NORTH WEST ARROW -->
+<!ENTITY szlig "&#x000DF;" ><!--LATIN SMALL LETTER SHARP S -->
+<!ENTITY target "&#x02316;" ><!--POSITION INDICATOR -->
+<!ENTITY tau "&#x003C4;" ><!--GREEK SMALL LETTER TAU -->
+<!ENTITY tbrk "&#x023B4;" ><!--TOP SQUARE BRACKET -->
+<!ENTITY tcaron "&#x00165;" ><!--LATIN SMALL LETTER T WITH CARON -->
+<!ENTITY tcedil "&#x00163;" ><!--LATIN SMALL LETTER T WITH CEDILLA -->
+<!ENTITY tcy "&#x00442;" ><!--CYRILLIC SMALL LETTER TE -->
+<!ENTITY tdot "&#x020DB;" ><!--COMBINING THREE DOTS ABOVE -->
+<!ENTITY telrec "&#x02315;" ><!--TELEPHONE RECORDER -->
+<!ENTITY tfr "&#x1D531;" ><!--MATHEMATICAL FRAKTUR SMALL T -->
+<!ENTITY there4 "&#x02234;" ><!--THEREFORE -->
+<!ENTITY therefore "&#x02234;" ><!--THEREFORE -->
+<!ENTITY theta "&#x003B8;" ><!--GREEK SMALL LETTER THETA -->
+<!ENTITY thetasym "&#x003D1;" ><!--GREEK THETA SYMBOL -->
+<!ENTITY thetav "&#x003D1;" ><!--GREEK THETA SYMBOL -->
+<!ENTITY thickapprox "&#x02248;" ><!--ALMOST EQUAL TO -->
+<!ENTITY thicksim "&#x0223C;" ><!--TILDE OPERATOR -->
+<!ENTITY thinsp "&#x02009;" ><!--THIN SPACE -->
+<!ENTITY thkap "&#x02248;" ><!--ALMOST EQUAL TO -->
+<!ENTITY thksim "&#x0223C;" ><!--TILDE OPERATOR -->
+<!ENTITY thorn "&#x000FE;" ><!--LATIN SMALL LETTER THORN -->
+<!ENTITY tilde "&#x002DC;" ><!--SMALL TILDE -->
+<!ENTITY times "&#x000D7;" ><!--MULTIPLICATION SIGN -->
+<!ENTITY timesb "&#x022A0;" ><!--SQUARED TIMES -->
+<!ENTITY timesbar "&#x02A31;" ><!--MULTIPLICATION SIGN WITH UNDERBAR -->
+<!ENTITY timesd "&#x02A30;" ><!--MULTIPLICATION SIGN WITH DOT ABOVE -->
+<!ENTITY tint "&#x0222D;" ><!--TRIPLE INTEGRAL -->
+<!ENTITY toea "&#x02928;" ><!--NORTH EAST ARROW AND SOUTH EAST ARROW -->
+<!ENTITY top "&#x022A4;" ><!--DOWN TACK -->
+<!ENTITY topbot "&#x02336;" ><!--APL FUNCTIONAL SYMBOL I-BEAM -->
+<!ENTITY topcir "&#x02AF1;" ><!--DOWN TACK WITH CIRCLE BELOW -->
+<!ENTITY topf "&#x1D565;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL T -->
+<!ENTITY topfork "&#x02ADA;" ><!--PITCHFORK WITH TEE TOP -->
+<!ENTITY tosa "&#x02929;" ><!--SOUTH EAST ARROW AND SOUTH WEST ARROW -->
+<!ENTITY tprime "&#x02034;" ><!--TRIPLE PRIME -->
+<!ENTITY trade "&#x02122;" ><!--TRADE MARK SIGN -->
+<!ENTITY triangle "&#x025B5;" ><!--WHITE UP-POINTING SMALL TRIANGLE -->
+<!ENTITY triangledown "&#x025BF;" ><!--WHITE DOWN-POINTING SMALL TRIANGLE -->
+<!ENTITY triangleleft "&#x025C3;" ><!--WHITE LEFT-POINTING SMALL TRIANGLE -->
+<!ENTITY trianglelefteq "&#x022B4;" ><!--NORMAL SUBGROUP OF OR EQUAL TO -->
+<!ENTITY triangleq "&#x0225C;" ><!--DELTA EQUAL TO -->
+<!ENTITY triangleright "&#x025B9;" ><!--WHITE RIGHT-POINTING SMALL TRIANGLE -->
+<!ENTITY trianglerighteq "&#x022B5;" ><!--CONTAINS AS NORMAL SUBGROUP OR EQUAL TO -->
+<!ENTITY tridot "&#x025EC;" ><!--WHITE UP-POINTING TRIANGLE WITH DOT -->
+<!ENTITY trie "&#x0225C;" ><!--DELTA EQUAL TO -->
+<!ENTITY triminus "&#x02A3A;" ><!--MINUS SIGN IN TRIANGLE -->
+<!ENTITY triplus "&#x02A39;" ><!--PLUS SIGN IN TRIANGLE -->
+<!ENTITY trisb "&#x029CD;" ><!--TRIANGLE WITH SERIFS AT BOTTOM -->
+<!ENTITY tritime "&#x02A3B;" ><!--MULTIPLICATION SIGN IN TRIANGLE -->
+<!ENTITY trpezium "&#x023E2;" ><!--WHITE TRAPEZIUM -->
+<!ENTITY tscr "&#x1D4C9;" ><!--MATHEMATICAL SCRIPT SMALL T -->
+<!ENTITY tscy "&#x00446;" ><!--CYRILLIC SMALL LETTER TSE -->
+<!ENTITY tshcy "&#x0045B;" ><!--CYRILLIC SMALL LETTER TSHE -->
+<!ENTITY tstrok "&#x00167;" ><!--LATIN SMALL LETTER T WITH STROKE -->
+<!ENTITY twixt "&#x0226C;" ><!--BETWEEN -->
+<!ENTITY twoheadleftarrow "&#x0219E;" ><!--LEFTWARDS TWO HEADED ARROW -->
+<!ENTITY twoheadrightarrow "&#x021A0;" ><!--RIGHTWARDS TWO HEADED ARROW -->
+<!ENTITY uArr "&#x021D1;" ><!--UPWARDS DOUBLE ARROW -->
+<!ENTITY uHar "&#x02963;" ><!--UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT -->
+<!ENTITY uacute "&#x000FA;" ><!--LATIN SMALL LETTER U WITH ACUTE -->
+<!ENTITY uarr "&#x02191;" ><!--UPWARDS ARROW -->
+<!ENTITY ubrcy "&#x0045E;" ><!--CYRILLIC SMALL LETTER SHORT U -->
+<!ENTITY ubreve "&#x0016D;" ><!--LATIN SMALL LETTER U WITH BREVE -->
+<!ENTITY ucirc "&#x000FB;" ><!--LATIN SMALL LETTER U WITH CIRCUMFLEX -->
+<!ENTITY ucy "&#x00443;" ><!--CYRILLIC SMALL LETTER U -->
+<!ENTITY udarr "&#x021C5;" ><!--UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW -->
+<!ENTITY udblac "&#x00171;" ><!--LATIN SMALL LETTER U WITH DOUBLE ACUTE -->
+<!ENTITY udhar "&#x0296E;" ><!--UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT -->
+<!ENTITY ufisht "&#x0297E;" ><!--UP FISH TAIL -->
+<!ENTITY ufr "&#x1D532;" ><!--MATHEMATICAL FRAKTUR SMALL U -->
+<!ENTITY ugrave "&#x000F9;" ><!--LATIN SMALL LETTER U WITH GRAVE -->
+<!ENTITY uharl "&#x021BF;" ><!--UPWARDS HARPOON WITH BARB LEFTWARDS -->
+<!ENTITY uharr "&#x021BE;" ><!--UPWARDS HARPOON WITH BARB RIGHTWARDS -->
+<!ENTITY uhblk "&#x02580;" ><!--UPPER HALF BLOCK -->
+<!ENTITY ulcorn "&#x0231C;" ><!--TOP LEFT CORNER -->
+<!ENTITY ulcorner "&#x0231C;" ><!--TOP LEFT CORNER -->
+<!ENTITY ulcrop "&#x0230F;" ><!--TOP LEFT CROP -->
+<!ENTITY ultri "&#x025F8;" ><!--UPPER LEFT TRIANGLE -->
+<!ENTITY umacr "&#x0016B;" ><!--LATIN SMALL LETTER U WITH MACRON -->
+<!ENTITY uml "&#x000A8;" ><!--DIAERESIS -->
+<!ENTITY uogon "&#x00173;" ><!--LATIN SMALL LETTER U WITH OGONEK -->
+<!ENTITY uopf "&#x1D566;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL U -->
+<!ENTITY uparrow "&#x02191;" ><!--UPWARDS ARROW -->
+<!ENTITY updownarrow "&#x02195;" ><!--UP DOWN ARROW -->
+<!ENTITY upharpoonleft "&#x021BF;" ><!--UPWARDS HARPOON WITH BARB LEFTWARDS -->
+<!ENTITY upharpoonright "&#x021BE;" ><!--UPWARDS HARPOON WITH BARB RIGHTWARDS -->
+<!ENTITY uplus "&#x0228E;" ><!--MULTISET UNION -->
+<!ENTITY upsi "&#x003C5;" ><!--GREEK SMALL LETTER UPSILON -->
+<!ENTITY upsih "&#x003D2;" ><!--GREEK UPSILON WITH HOOK SYMBOL -->
+<!ENTITY upsilon "&#x003C5;" ><!--GREEK SMALL LETTER UPSILON -->
+<!ENTITY upuparrows "&#x021C8;" ><!--UPWARDS PAIRED ARROWS -->
+<!ENTITY urcorn "&#x0231D;" ><!--TOP RIGHT CORNER -->
+<!ENTITY urcorner "&#x0231D;" ><!--TOP RIGHT CORNER -->
+<!ENTITY urcrop "&#x0230E;" ><!--TOP RIGHT CROP -->
+<!ENTITY uring "&#x0016F;" ><!--LATIN SMALL LETTER U WITH RING ABOVE -->
+<!ENTITY urtri "&#x025F9;" ><!--UPPER RIGHT TRIANGLE -->
+<!ENTITY uscr "&#x1D4CA;" ><!--MATHEMATICAL SCRIPT SMALL U -->
+<!ENTITY utdot "&#x022F0;" ><!--UP RIGHT DIAGONAL ELLIPSIS -->
+<!ENTITY utilde "&#x00169;" ><!--LATIN SMALL LETTER U WITH TILDE -->
+<!ENTITY utri "&#x025B5;" ><!--WHITE UP-POINTING SMALL TRIANGLE -->
+<!ENTITY utrif "&#x025B4;" ><!--BLACK UP-POINTING SMALL TRIANGLE -->
+<!ENTITY uuarr "&#x021C8;" ><!--UPWARDS PAIRED ARROWS -->
+<!ENTITY uuml "&#x000FC;" ><!--LATIN SMALL LETTER U WITH DIAERESIS -->
+<!ENTITY uwangle "&#x029A7;" ><!--OBLIQUE ANGLE OPENING DOWN -->
+<!ENTITY vArr "&#x021D5;" ><!--UP DOWN DOUBLE ARROW -->
+<!ENTITY vBar "&#x02AE8;" ><!--SHORT UP TACK WITH UNDERBAR -->
+<!ENTITY vBarv "&#x02AE9;" ><!--SHORT UP TACK ABOVE SHORT DOWN TACK -->
+<!ENTITY vDash "&#x022A8;" ><!--TRUE -->
+<!ENTITY vangrt "&#x0299C;" ><!--RIGHT ANGLE VARIANT WITH SQUARE -->
+<!ENTITY varepsilon "&#x003F5;" ><!--GREEK LUNATE EPSILON SYMBOL -->
+<!ENTITY varkappa "&#x003F0;" ><!--GREEK KAPPA SYMBOL -->
+<!ENTITY varnothing "&#x02205;" ><!--EMPTY SET -->
+<!ENTITY varphi "&#x003D5;" ><!--GREEK PHI SYMBOL -->
+<!ENTITY varpi "&#x003D6;" ><!--GREEK PI SYMBOL -->
+<!ENTITY varpropto "&#x0221D;" ><!--PROPORTIONAL TO -->
+<!ENTITY varr "&#x02195;" ><!--UP DOWN ARROW -->
+<!ENTITY varrho "&#x003F1;" ><!--GREEK RHO SYMBOL -->
+<!ENTITY varsigma "&#x003C2;" ><!--GREEK SMALL LETTER FINAL SIGMA -->
+<!ENTITY varsubsetneq "&#x0228A;&#x0FE00;" ><!--SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -->
+<!ENTITY varsubsetneqq "&#x02ACB;&#x0FE00;" ><!--SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members -->
+<!ENTITY varsupsetneq "&#x0228B;&#x0FE00;" ><!--SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -->
+<!ENTITY varsupsetneqq "&#x02ACC;&#x0FE00;" ><!--SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members -->
+<!ENTITY vartheta "&#x003D1;" ><!--GREEK THETA SYMBOL -->
+<!ENTITY vartriangleleft "&#x022B2;" ><!--NORMAL SUBGROUP OF -->
+<!ENTITY vartriangleright "&#x022B3;" ><!--CONTAINS AS NORMAL SUBGROUP -->
+<!ENTITY vcy "&#x00432;" ><!--CYRILLIC SMALL LETTER VE -->
+<!ENTITY vdash "&#x022A2;" ><!--RIGHT TACK -->
+<!ENTITY vee "&#x02228;" ><!--LOGICAL OR -->
+<!ENTITY veebar "&#x022BB;" ><!--XOR -->
+<!ENTITY veeeq "&#x0225A;" ><!--EQUIANGULAR TO -->
+<!ENTITY vellip "&#x022EE;" ><!--VERTICAL ELLIPSIS -->
+<!ENTITY verbar "&#x0007C;" ><!--VERTICAL LINE -->
+<!ENTITY vert "&#x0007C;" ><!--VERTICAL LINE -->
+<!ENTITY vfr "&#x1D533;" ><!--MATHEMATICAL FRAKTUR SMALL V -->
+<!ENTITY vltri "&#x022B2;" ><!--NORMAL SUBGROUP OF -->
+<!ENTITY vnsub "&#x02282;&#x020D2;" ><!--SUBSET OF with vertical line -->
+<!ENTITY vnsup "&#x02283;&#x020D2;" ><!--SUPERSET OF with vertical line -->
+<!ENTITY vopf "&#x1D567;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL V -->
+<!ENTITY vprop "&#x0221D;" ><!--PROPORTIONAL TO -->
+<!ENTITY vrtri "&#x022B3;" ><!--CONTAINS AS NORMAL SUBGROUP -->
+<!ENTITY vscr "&#x1D4CB;" ><!--MATHEMATICAL SCRIPT SMALL V -->
+<!ENTITY vsubnE "&#x02ACB;&#x0FE00;" ><!--SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members -->
+<!ENTITY vsubne "&#x0228A;&#x0FE00;" ><!--SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -->
+<!ENTITY vsupnE "&#x02ACC;&#x0FE00;" ><!--SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members -->
+<!ENTITY vsupne "&#x0228B;&#x0FE00;" ><!--SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -->
+<!ENTITY vzigzag "&#x0299A;" ><!--VERTICAL ZIGZAG LINE -->
+<!ENTITY wcirc "&#x00175;" ><!--LATIN SMALL LETTER W WITH CIRCUMFLEX -->
+<!ENTITY wedbar "&#x02A5F;" ><!--LOGICAL AND WITH UNDERBAR -->
+<!ENTITY wedge "&#x02227;" ><!--LOGICAL AND -->
+<!ENTITY wedgeq "&#x02259;" ><!--ESTIMATES -->
+<!ENTITY weierp "&#x02118;" ><!--SCRIPT CAPITAL P -->
+<!ENTITY wfr "&#x1D534;" ><!--MATHEMATICAL FRAKTUR SMALL W -->
+<!ENTITY wopf "&#x1D568;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL W -->
+<!ENTITY wp "&#x02118;" ><!--SCRIPT CAPITAL P -->
+<!ENTITY wr "&#x02240;" ><!--WREATH PRODUCT -->
+<!ENTITY wreath "&#x02240;" ><!--WREATH PRODUCT -->
+<!ENTITY wscr "&#x1D4CC;" ><!--MATHEMATICAL SCRIPT SMALL W -->
+<!ENTITY xcap "&#x022C2;" ><!--N-ARY INTERSECTION -->
+<!ENTITY xcirc "&#x025EF;" ><!--LARGE CIRCLE -->
+<!ENTITY xcup "&#x022C3;" ><!--N-ARY UNION -->
+<!ENTITY xdtri "&#x025BD;" ><!--WHITE DOWN-POINTING TRIANGLE -->
+<!ENTITY xfr "&#x1D535;" ><!--MATHEMATICAL FRAKTUR SMALL X -->
+<!ENTITY xhArr "&#x027FA;" ><!--LONG LEFT RIGHT DOUBLE ARROW -->
+<!ENTITY xharr "&#x027F7;" ><!--LONG LEFT RIGHT ARROW -->
+<!ENTITY xi "&#x003BE;" ><!--GREEK SMALL LETTER XI -->
+<!ENTITY xlArr "&#x027F8;" ><!--LONG LEFTWARDS DOUBLE ARROW -->
+<!ENTITY xlarr "&#x027F5;" ><!--LONG LEFTWARDS ARROW -->
+<!ENTITY xmap "&#x027FC;" ><!--LONG RIGHTWARDS ARROW FROM BAR -->
+<!ENTITY xnis "&#x022FB;" ><!--CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE -->
+<!ENTITY xodot "&#x02A00;" ><!--N-ARY CIRCLED DOT OPERATOR -->
+<!ENTITY xopf "&#x1D569;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL X -->
+<!ENTITY xoplus "&#x02A01;" ><!--N-ARY CIRCLED PLUS OPERATOR -->
+<!ENTITY xotime "&#x02A02;" ><!--N-ARY CIRCLED TIMES OPERATOR -->
+<!ENTITY xrArr "&#x027F9;" ><!--LONG RIGHTWARDS DOUBLE ARROW -->
+<!ENTITY xrarr "&#x027F6;" ><!--LONG RIGHTWARDS ARROW -->
+<!ENTITY xscr "&#x1D4CD;" ><!--MATHEMATICAL SCRIPT SMALL X -->
+<!ENTITY xsqcup "&#x02A06;" ><!--N-ARY SQUARE UNION OPERATOR -->
+<!ENTITY xuplus "&#x02A04;" ><!--N-ARY UNION OPERATOR WITH PLUS -->
+<!ENTITY xutri "&#x025B3;" ><!--WHITE UP-POINTING TRIANGLE -->
+<!ENTITY xvee "&#x022C1;" ><!--N-ARY LOGICAL OR -->
+<!ENTITY xwedge "&#x022C0;" ><!--N-ARY LOGICAL AND -->
+<!ENTITY yacute "&#x000FD;" ><!--LATIN SMALL LETTER Y WITH ACUTE -->
+<!ENTITY yacy "&#x0044F;" ><!--CYRILLIC SMALL LETTER YA -->
+<!ENTITY ycirc "&#x00177;" ><!--LATIN SMALL LETTER Y WITH CIRCUMFLEX -->
+<!ENTITY ycy "&#x0044B;" ><!--CYRILLIC SMALL LETTER YERU -->
+<!ENTITY yen "&#x000A5;" ><!--YEN SIGN -->
+<!ENTITY yfr "&#x1D536;" ><!--MATHEMATICAL FRAKTUR SMALL Y -->
+<!ENTITY yicy "&#x00457;" ><!--CYRILLIC SMALL LETTER YI -->
+<!ENTITY yopf "&#x1D56A;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL Y -->
+<!ENTITY yscr "&#x1D4CE;" ><!--MATHEMATICAL SCRIPT SMALL Y -->
+<!ENTITY yucy "&#x0044E;" ><!--CYRILLIC SMALL LETTER YU -->
+<!ENTITY yuml "&#x000FF;" ><!--LATIN SMALL LETTER Y WITH DIAERESIS -->
+<!ENTITY zacute "&#x0017A;" ><!--LATIN SMALL LETTER Z WITH ACUTE -->
+<!ENTITY zcaron "&#x0017E;" ><!--LATIN SMALL LETTER Z WITH CARON -->
+<!ENTITY zcy "&#x00437;" ><!--CYRILLIC SMALL LETTER ZE -->
+<!ENTITY zdot "&#x0017C;" ><!--LATIN SMALL LETTER Z WITH DOT ABOVE -->
+<!ENTITY zeetrf "&#x02128;" ><!--BLACK-LETTER CAPITAL Z -->
+<!ENTITY zeta "&#x003B6;" ><!--GREEK SMALL LETTER ZETA -->
+<!ENTITY zfr "&#x1D537;" ><!--MATHEMATICAL FRAKTUR SMALL Z -->
+<!ENTITY zhcy "&#x00436;" ><!--CYRILLIC SMALL LETTER ZHE -->
+<!ENTITY zigrarr "&#x021DD;" ><!--RIGHTWARDS SQUIGGLE ARROW -->
+<!ENTITY zopf "&#x1D56B;" ><!--MATHEMATICAL DOUBLE-STRUCK SMALL Z -->
+<!ENTITY zscr "&#x1D4CF;" ><!--MATHEMATICAL SCRIPT SMALL Z -->
+<!ENTITY zwj "&#x0200D;" ><!--ZERO WIDTH JOINER -->
+<!ENTITY zwnj "&#x0200C;" ><!--ZERO WIDTH NON-JOINER -->
diff --git a/dom/xml/moz.build b/dom/xml/moz.build
new file mode 100644
index 0000000000..39fbb901f2
--- /dev/null
+++ b/dom/xml/moz.build
@@ -0,0 +1,51 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Core", "XML")
+
+DIRS += ["resources"]
+
+MOCHITEST_MANIFESTS += ["test/mochitest.ini"]
+
+EXPORTS += [
+ "nsIXMLContentSink.h",
+]
+
+EXPORTS.mozilla.dom += [
+ "CDATASection.h",
+ "nsXMLElement.h",
+ "ProcessingInstruction.h",
+ "XMLDocument.h",
+ "XMLStylesheetProcessingInstruction.h",
+]
+
+UNIFIED_SOURCES += [
+ "CDATASection.cpp",
+ "nsXMLContentSink.cpp",
+ "nsXMLElement.cpp",
+ "nsXMLFragmentContentSink.cpp",
+ "nsXMLPrettyPrinter.cpp",
+ "ProcessingInstruction.cpp",
+ "XMLDocument.cpp",
+ "XMLStylesheetProcessingInstruction.cpp",
+]
+
+FINAL_LIBRARY = "xul"
+
+LOCAL_INCLUDES += [
+ "/caps",
+ "/dom/base",
+ "/dom/html",
+ "/dom/xslt/base",
+ "/dom/xul",
+ "/layout/style",
+ "/parser/htmlparser",
+]
+
+RESOURCE_FILES.dtd += [
+ "htmlmathml-f.ent",
+]
diff --git a/dom/xml/nsIXMLContentSink.h b/dom/xml/nsIXMLContentSink.h
new file mode 100644
index 0000000000..eba9b356f0
--- /dev/null
+++ b/dom/xml/nsIXMLContentSink.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef nsIXMLContentSink_h___
+#define nsIXMLContentSink_h___
+
+#include "nsIContentSink.h"
+#include "nsISupports.h"
+
+class nsIURI;
+class nsIChannel;
+namespace mozilla::dom {
+class Document;
+} // namespace mozilla::dom
+
+#define NS_IXMLCONTENT_SINK_IID \
+ { \
+ 0x63fedea0, 0x9b0f, 0x4d64, { \
+ 0x9b, 0xa5, 0x37, 0xc6, 0x99, 0x73, 0x29, 0x35 \
+ } \
+ }
+
+/**
+ * This interface represents a content sink for generic XML files.
+ * The goal of this sink is to deal with XML documents that do not
+ * have pre-built semantics, though it may also be implemented for
+ * cases in which semantics are hard-wired.
+ *
+ * The expectation is that the parser has already performed
+ * well-formedness and validity checking.
+ *
+ * XXX The expectation is that entity expansion will be done by the sink
+ * itself. This would require, however, that the sink has the ability
+ * to query the parser for entity replacement text.
+ *
+ * XXX This interface does not contain a mechanism for the sink to
+ * get specific schema/DTD information from the parser. This information
+ * may be necessary for entity expansion. It is also necessary for
+ * building the DOM portions that relate to the schema.
+ *
+ * XXX This interface does not deal with the presence of an external
+ * subset. It seems possible that this could be dealt with completely
+ * at the parser level.
+ */
+
+class nsIXMLContentSink : public nsIContentSink {
+ public:
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXMLCONTENT_SINK_IID)
+ virtual bool IsPrettyPrintXML() const { return false; }
+ virtual bool IsPrettyPrintHasSpecialRoot() const { return false; }
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIXMLContentSink, NS_IXMLCONTENT_SINK_IID)
+
+nsresult NS_NewXMLContentSink(nsIXMLContentSink** aInstancePtrResult,
+ mozilla::dom::Document* aDoc, nsIURI* aURL,
+ nsISupports* aContainer, nsIChannel* aChannel);
+
+#endif // nsIXMLContentSink_h___
diff --git a/dom/xml/nsXMLContentSink.cpp b/dom/xml/nsXMLContentSink.cpp
new file mode 100644
index 0000000000..4080a10b93
--- /dev/null
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -0,0 +1,1536 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsCOMPtr.h"
+#include "nsXMLContentSink.h"
+#include "nsIParser.h"
+#include "mozilla/dom/Document.h"
+#include "nsIContent.h"
+#include "nsIURI.h"
+#include "nsNetUtil.h"
+#include "nsHTMLParts.h"
+#include "nsCRT.h"
+#include "mozilla/StyleSheetInlines.h"
+#include "mozilla/css/Loader.h"
+#include "nsGkAtoms.h"
+#include "nsContentUtils.h"
+#include "nsDocElementCreatedNotificationRunner.h"
+#include "nsIDocShell.h"
+#include "nsIScriptContext.h"
+#include "nsNameSpaceManager.h"
+#include "nsIScriptSecurityManager.h"
+#include "nsIContentViewer.h"
+#include "prtime.h"
+#include "mozilla/Logging.h"
+#include "nsRect.h"
+#include "nsIScriptElement.h"
+#include "nsReadableUtils.h"
+#include "nsUnicharUtils.h"
+#include "nsIChannel.h"
+#include "nsXMLPrettyPrinter.h"
+#include "nsNodeInfoManager.h"
+#include "nsContentCreatorFunctions.h"
+#include "nsIContentPolicy.h"
+#include "nsContentPolicyUtils.h"
+#include "nsError.h"
+#include "nsIScriptGlobalObject.h"
+#include "mozAutoDocUpdate.h"
+#include "nsMimeTypes.h"
+#include "nsHtml5SVGLoadDispatcher.h"
+#include "nsTextNode.h"
+#include "mozilla/dom/CDATASection.h"
+#include "mozilla/dom/Comment.h"
+#include "mozilla/dom/DocumentType.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/HTMLTemplateElement.h"
+#include "mozilla/dom/MutationObservers.h"
+#include "mozilla/dom/ProcessingInstruction.h"
+#include "mozilla/dom/ScriptLoader.h"
+#include "mozilla/dom/txMozillaXSLTProcessor.h"
+#include "mozilla/CycleCollectedJSContext.h"
+#include "mozilla/LoadInfo.h"
+#include "mozilla/UseCounter.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+// XXX Open Issues:
+// 1) what's not allowed - We need to figure out which HTML tags
+// (prefixed with a HTML namespace qualifier) are explicitly not
+// allowed (if any).
+// 2) factoring code with nsHTMLContentSink - There's some amount of
+// common code between this and the HTML content sink. This will
+// increase as we support more and more HTML elements. How can code
+// from the code be factored?
+
+nsresult NS_NewXMLContentSink(nsIXMLContentSink** aResult, Document* aDoc,
+ nsIURI* aURI, nsISupports* aContainer,
+ nsIChannel* aChannel) {
+ MOZ_ASSERT(nullptr != aResult, "null ptr");
+ if (nullptr == aResult) {
+ return NS_ERROR_NULL_POINTER;
+ }
+ RefPtr<nsXMLContentSink> it = new nsXMLContentSink();
+
+ nsresult rv = it->Init(aDoc, aURI, aContainer, aChannel);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ it.forget(aResult);
+ return NS_OK;
+}
+
+nsXMLContentSink::nsXMLContentSink()
+ : mState(eXMLContentSinkState_InProlog),
+ mTextLength(0),
+ mNotifyLevel(0),
+ mPrettyPrintXML(true),
+ mPrettyPrintHasSpecialRoot(0),
+ mPrettyPrintHasFactoredElements(0),
+ mPrettyPrinting(0),
+ mPreventScriptExecution(0) {
+ PodArrayZero(mText);
+}
+
+nsXMLContentSink::~nsXMLContentSink() = default;
+
+nsresult nsXMLContentSink::Init(Document* aDoc, nsIURI* aURI,
+ nsISupports* aContainer, nsIChannel* aChannel) {
+ nsresult rv = nsContentSink::Init(aDoc, aURI, aContainer, aChannel);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ aDoc->AddObserver(this);
+ mIsDocumentObserver = true;
+
+ if (!mDocShell) {
+ mPrettyPrintXML = false;
+ }
+
+ mState = eXMLContentSinkState_InProlog;
+ mDocElement = nullptr;
+
+ return NS_OK;
+}
+
+inline void ImplCycleCollectionTraverse(
+ nsCycleCollectionTraversalCallback& aCallback,
+ nsXMLContentSink::StackNode& aField, const char* aName,
+ uint32_t aFlags = 0) {
+ ImplCycleCollectionTraverse(aCallback, aField.mContent, aName, aFlags);
+}
+
+inline void ImplCycleCollectionUnlink(nsXMLContentSink::StackNode& aField) {
+ ImplCycleCollectionUnlink(aField.mContent);
+}
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLContentSink)
+ NS_INTERFACE_MAP_ENTRY(nsIContentSink)
+ NS_INTERFACE_MAP_ENTRY(nsIXMLContentSink)
+ NS_INTERFACE_MAP_ENTRY(nsIExpatSink)
+ NS_INTERFACE_MAP_ENTRY(nsITransformObserver)
+NS_INTERFACE_MAP_END_INHERITING(nsContentSink)
+
+NS_IMPL_ADDREF_INHERITED(nsXMLContentSink, nsContentSink)
+NS_IMPL_RELEASE_INHERITED(nsXMLContentSink, nsContentSink)
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(nsXMLContentSink, nsContentSink,
+ mCurrentHead, mDocElement, mLastTextNode,
+ mContentStack, mDocumentChildren)
+
+// nsIContentSink
+NS_IMETHODIMP
+nsXMLContentSink::WillParse(void) { return WillParseImpl(); }
+
+NS_IMETHODIMP
+nsXMLContentSink::WillBuildModel(nsDTDMode aDTDMode) {
+ WillBuildModelImpl();
+
+ // Notify document that the load is beginning
+ mDocument->BeginLoad();
+
+ // Check for correct load-command for maybe prettyprinting
+ if (mPrettyPrintXML) {
+ nsAutoCString command;
+ GetParser()->GetCommand(command);
+ if (!command.EqualsLiteral("view")) {
+ mPrettyPrintXML = false;
+ }
+ }
+
+ return NS_OK;
+}
+
+bool nsXMLContentSink::CanStillPrettyPrint() {
+ return mPrettyPrintXML &&
+ (!mPrettyPrintHasFactoredElements || mPrettyPrintHasSpecialRoot);
+}
+
+nsresult nsXMLContentSink::MaybePrettyPrint() {
+ if (!CanStillPrettyPrint()) {
+ mPrettyPrintXML = false;
+
+ return NS_OK;
+ }
+
+ {
+ // Try to perform a microtask checkpoint; this avoids always breaking
+ // pretty-printing if webextensions insert new content right after the
+ // document loads.
+ nsAutoMicroTask mt;
+ }
+
+ // stop observing in order to avoid crashing when replacing content
+ mDocument->RemoveObserver(this);
+ mIsDocumentObserver = false;
+
+ // Reenable the CSSLoader so that the prettyprinting stylesheets can load
+ if (mCSSLoader) {
+ mCSSLoader->SetEnabled(true);
+ }
+
+ RefPtr<nsXMLPrettyPrinter> printer;
+ nsresult rv = NS_NewXMLPrettyPrinter(getter_AddRefs(printer));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ bool isPrettyPrinting;
+ rv = printer->PrettyPrint(mDocument, &isPrettyPrinting);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mPrettyPrinting = isPrettyPrinting;
+ return NS_OK;
+}
+
+static void CheckXSLTParamPI(ProcessingInstruction* aPi,
+ nsIDocumentTransformer* aProcessor,
+ nsINode* aSource) {
+ nsAutoString target, data;
+ aPi->GetTarget(target);
+
+ // Check for namespace declarations
+ if (target.EqualsLiteral("xslt-param-namespace")) {
+ aPi->GetData(data);
+ nsAutoString prefix, namespaceAttr;
+ nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::prefix, prefix);
+ if (!prefix.IsEmpty() && nsContentUtils::GetPseudoAttributeValue(
+ data, nsGkAtoms::_namespace, namespaceAttr)) {
+ aProcessor->AddXSLTParamNamespace(prefix, namespaceAttr);
+ }
+ }
+
+ // Check for actual parameters
+ else if (target.EqualsLiteral("xslt-param")) {
+ aPi->GetData(data);
+ nsAutoString name, namespaceAttr, select, value;
+ nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::name, name);
+ nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::_namespace,
+ namespaceAttr);
+ if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::select,
+ select)) {
+ select.SetIsVoid(true);
+ }
+ if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::value,
+ value)) {
+ value.SetIsVoid(true);
+ }
+ if (!name.IsEmpty()) {
+ aProcessor->AddXSLTParam(name, namespaceAttr, select, value, aSource);
+ }
+ }
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::DidBuildModel(bool aTerminated) {
+ if (!mParser) {
+ // If mParser is null, this parse has already been terminated and must
+ // not been terminated again. However, Document may still think that
+ // the parse has not been terminated and call back into here in the case
+ // where the XML parser has finished but the XSLT transform associated
+ // with the document has not.
+ return NS_OK;
+ }
+
+ FlushTags();
+
+ DidBuildModelImpl(aTerminated);
+
+ if (mXSLTProcessor) {
+ // stop observing in order to avoid crashing when replacing content
+ mDocument->RemoveObserver(this);
+ mIsDocumentObserver = false;
+
+ ErrorResult rv;
+ RefPtr<DocumentFragment> source = mDocument->CreateDocumentFragment();
+ for (nsIContent* child : mDocumentChildren) {
+ // XPath data model doesn't have DocumentType nodes.
+ if (child->NodeType() != nsINode::DOCUMENT_TYPE_NODE) {
+ source->AppendChild(*child, rv);
+ if (rv.Failed()) {
+ return rv.StealNSResult();
+ }
+ }
+ }
+
+ // Check for xslt-param and xslt-param-namespace PIs
+ for (nsIContent* child : mDocumentChildren) {
+ if (auto pi = ProcessingInstruction::FromNode(child)) {
+ CheckXSLTParamPI(pi, mXSLTProcessor, source);
+ } else if (child->IsElement()) {
+ // Only honor PIs in the prolog
+ break;
+ }
+ }
+
+ mXSLTProcessor->SetSourceContentModel(source);
+ // Since the processor now holds a reference to us we drop our reference
+ // to it to avoid owning cycles
+ mXSLTProcessor = nullptr;
+ } else {
+ // Kick off layout for non-XSLT transformed documents.
+
+ // Check if we want to prettyprint
+ MaybePrettyPrint();
+
+ bool startLayout = true;
+
+ if (mPrettyPrinting) {
+ NS_ASSERTION(!mPendingSheetCount, "Shouldn't have pending sheets here!");
+
+ // We're pretty-printing now. See whether we should wait up on
+ // stylesheet loads
+ if (mDocument->CSSLoader()->HasPendingLoads()) {
+ mDocument->CSSLoader()->AddObserver(this);
+ // wait for those sheets to load
+ startLayout = false;
+ }
+ }
+
+ if (startLayout) {
+ StartLayout(false);
+
+ ScrollToRef();
+ }
+
+ mDocument->RemoveObserver(this);
+ mIsDocumentObserver = false;
+
+ mDocument->EndLoad();
+
+ DropParserAndPerfHint();
+ }
+
+ return NS_OK;
+}
+
+nsresult nsXMLContentSink::OnDocumentCreated(Document* aSourceDocument,
+ Document* aResultDocument) {
+ aResultDocument->SetDocWriteDisabled(true);
+
+ nsCOMPtr<nsIContentViewer> contentViewer;
+ mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
+ // Make sure that we haven't loaded a new document into the contentviewer
+ // after starting the XSLT transform.
+ if (contentViewer && contentViewer->GetDocument() == aSourceDocument) {
+ return contentViewer->SetDocumentInternal(aResultDocument, true);
+ }
+ return NS_OK;
+}
+
+nsresult nsXMLContentSink::OnTransformDone(Document* aSourceDocument,
+ nsresult aResult,
+ Document* aResultDocument) {
+ MOZ_ASSERT(aResultDocument,
+ "Don't notify about transform end without a document.");
+
+ mDocumentChildren.Clear();
+
+ nsCOMPtr<nsIContentViewer> contentViewer;
+ mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
+
+ RefPtr<Document> originalDocument = mDocument;
+ bool blockingOnload = mIsBlockingOnload;
+
+ // Make sure that we haven't loaded a new document into the contentviewer
+ // after starting the XSLT transform.
+ if (contentViewer && (contentViewer->GetDocument() == aSourceDocument ||
+ contentViewer->GetDocument() == aResultDocument)) {
+ if (NS_FAILED(aResult)) {
+ // Transform failed.
+ aResultDocument->SetMayStartLayout(false);
+ // We have an error document.
+ contentViewer->SetDocument(aResultDocument);
+ }
+
+ if (!mRunsToCompletion) {
+ // This BlockOnload call corresponds to the UnblockOnload call in
+ // nsContentSink::DropParserAndPerfHint.
+ aResultDocument->BlockOnload();
+ mIsBlockingOnload = true;
+ }
+ // Transform succeeded, or it failed and we have an error document to
+ // display.
+ mDocument = aResultDocument;
+ aResultDocument->SetDocWriteDisabled(false);
+
+ // Notify document observers that all the content has been stuck
+ // into the document.
+ // XXX do we need to notify for things like PIs? Or just the
+ // documentElement?
+ nsIContent* rootElement = mDocument->GetRootElement();
+ if (rootElement) {
+ NS_ASSERTION(mDocument->ComputeIndexOf(rootElement).isSome(),
+ "rootElement not in doc?");
+ mDocument->BeginUpdate();
+ MutationObservers::NotifyContentInserted(mDocument, rootElement);
+ mDocument->EndUpdate();
+ }
+
+ // Start the layout process
+ StartLayout(false);
+
+ ScrollToRef();
+ }
+
+ originalDocument->EndLoad();
+ if (blockingOnload) {
+ // This UnblockOnload call corresponds to the BlockOnload call in
+ // nsContentSink::WillBuildModelImpl.
+ originalDocument->UnblockOnload(true);
+ }
+
+ DropParserAndPerfHint();
+
+ // By this point, the result document has been set in the content viewer. But
+ // the content viewer does not call Destroy on the original document, so we
+ // won't end up reporting document use counters. It's possible we should be
+ // detaching the document from the window, but for now, we call
+ // ReportDocumentUseCounters on the original document here, to avoid
+ // assertions in ~Document about not having reported them.
+ originalDocument->ReportDocumentUseCounters();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred,
+ nsresult aStatus) {
+ if (!mPrettyPrinting) {
+ return nsContentSink::StyleSheetLoaded(aSheet, aWasDeferred, aStatus);
+ }
+
+ if (!mDocument->CSSLoader()->HasPendingLoads()) {
+ mDocument->CSSLoader()->RemoveObserver(this);
+ StartLayout(false);
+ ScrollToRef();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::WillInterrupt(void) { return WillInterruptImpl(); }
+
+void nsXMLContentSink::WillResume() { WillResumeImpl(); }
+
+NS_IMETHODIMP
+nsXMLContentSink::SetParser(nsParserBase* aParser) {
+ MOZ_ASSERT(aParser, "Should have a parser here!");
+ mParser = aParser;
+ return NS_OK;
+}
+
+static bool FindIsAttrValue(const char16_t** aAtts, const char16_t** aResult) {
+ RefPtr<nsAtom> prefix, localName;
+ for (; *aAtts; aAtts += 2) {
+ int32_t nameSpaceID;
+ nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
+ getter_AddRefs(localName), &nameSpaceID);
+ if (nameSpaceID == kNameSpaceID_None && localName == nsGkAtoms::is) {
+ *aResult = aAtts[1];
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+nsresult nsXMLContentSink::CreateElement(
+ const char16_t** aAtts, uint32_t aAttsCount,
+ mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
+ uint32_t aColumnNumber, nsIContent** aResult, bool* aAppendContent,
+ FromParser aFromParser) {
+ NS_ASSERTION(aNodeInfo, "can't create element without nodeinfo");
+
+ *aResult = nullptr;
+ *aAppendContent = true;
+ nsresult rv = NS_OK;
+
+ RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
+ RefPtr<Element> content;
+
+ const char16_t* is = nullptr;
+ if ((aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML) ||
+ aNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) &&
+ FindIsAttrValue(aAtts, &is)) {
+ const nsDependentString isStr(is);
+ rv = NS_NewElement(getter_AddRefs(content), ni.forget(), aFromParser,
+ &isStr);
+ } else {
+ rv = NS_NewElement(getter_AddRefs(content), ni.forget(), aFromParser);
+ }
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) ||
+ aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_SVG)) {
+ nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(content);
+ if (sele) {
+ sele->SetScriptLineNumber(aLineNumber);
+ sele->SetScriptColumnNumber(aColumnNumber);
+ sele->SetCreatorParser(GetParser());
+ } else {
+ MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
+ "Node didn't QI to script, but SVG wasn't disabled.");
+ }
+ }
+
+ // XHTML needs some special attention
+ if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
+ mPrettyPrintHasFactoredElements = true;
+ } else {
+ // If we care, find out if we just used a special factory.
+ if (!mPrettyPrintHasFactoredElements && !mPrettyPrintHasSpecialRoot &&
+ mPrettyPrintXML) {
+ mPrettyPrintHasFactoredElements =
+ nsNameSpaceManager::GetInstance()->HasElementCreator(
+ aNodeInfo->NamespaceID());
+ }
+
+ if (!aNodeInfo->NamespaceEquals(kNameSpaceID_SVG)) {
+ content.forget(aResult);
+
+ return NS_OK;
+ }
+ }
+
+ if (aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML) ||
+ aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_XHTML) ||
+ aNodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_SVG)) {
+ if (auto* linkStyle = LinkStyle::FromNode(*content)) {
+ if (aFromParser) {
+ linkStyle->SetEnableUpdates(false);
+ }
+ if (!aNodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML)) {
+ linkStyle->SetLineNumber(aFromParser ? aLineNumber : 0);
+ linkStyle->SetColumnNumber(aFromParser ? aColumnNumber : 0);
+ }
+ }
+ }
+
+ content.forget(aResult);
+
+ return NS_OK;
+}
+
+nsresult nsXMLContentSink::CloseElement(nsIContent* aContent) {
+ NS_ASSERTION(aContent, "missing element to close");
+
+ mozilla::dom::NodeInfo* nodeInfo = aContent->NodeInfo();
+
+ // Some HTML nodes need DoneAddingChildren() called to initialize
+ // properly (eg form state restoration).
+ if (nsIContent::RequiresDoneAddingChildren(nodeInfo->NamespaceID(),
+ nodeInfo->NameAtom())) {
+ aContent->DoneAddingChildren(HaveNotifiedForCurrentContent());
+ }
+
+ if (IsMonolithicContainer(nodeInfo)) {
+ mInMonolithicContainer--;
+ }
+
+ if (!nodeInfo->NamespaceEquals(kNameSpaceID_XHTML) &&
+ !nodeInfo->NamespaceEquals(kNameSpaceID_SVG)) {
+ return NS_OK;
+ }
+
+ if (nodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) ||
+ nodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_SVG)) {
+ nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aContent);
+ if (!sele) {
+ MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
+ "Node didn't QI to script, but SVG wasn't disabled.");
+ return NS_OK;
+ }
+
+ if (mPreventScriptExecution) {
+ sele->PreventExecution();
+ return NS_OK;
+ }
+
+ // Always check the clock in nsContentSink right after a script
+ StopDeflecting();
+
+ // Now tell the script that it's ready to go. This may execute the script
+ // or return true, or neither if the script doesn't need executing.
+ bool block = sele->AttemptToExecute();
+ if (mParser) {
+ if (block) {
+ GetParser()->BlockParser();
+ }
+
+ // If the parser got blocked, make sure to return the appropriate rv.
+ // I'm not sure if this is actually needed or not.
+ if (!mParser->IsParserEnabled()) {
+ block = true;
+ }
+ }
+
+ return block ? NS_ERROR_HTMLPARSER_BLOCK : NS_OK;
+ }
+
+ nsresult rv = NS_OK;
+ if (nodeInfo->Equals(nsGkAtoms::link, kNameSpaceID_XHTML) ||
+ nodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_XHTML) ||
+ nodeInfo->Equals(nsGkAtoms::style, kNameSpaceID_SVG)) {
+ if (auto* linkStyle = LinkStyle::FromNode(*aContent)) {
+ linkStyle->SetEnableUpdates(true);
+ auto updateOrError =
+ linkStyle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this);
+ if (updateOrError.isErr()) {
+ rv = updateOrError.unwrapErr();
+ } else if (updateOrError.unwrap().ShouldBlock() && !mRunsToCompletion) {
+ ++mPendingSheetCount;
+ mScriptLoader->AddParserBlockingScriptExecutionBlocker();
+ }
+ }
+ }
+
+ return rv;
+}
+
+nsresult nsXMLContentSink::AddContentAsLeaf(nsIContent* aContent) {
+ nsresult result = NS_OK;
+
+ if (mState == eXMLContentSinkState_InProlog) {
+ NS_ASSERTION(mDocument, "Fragments have no prolog");
+ mDocumentChildren.AppendElement(aContent);
+ } else if (mState == eXMLContentSinkState_InEpilog) {
+ NS_ASSERTION(mDocument, "Fragments have no epilog");
+ if (mXSLTProcessor) {
+ mDocumentChildren.AppendElement(aContent);
+ } else {
+ mDocument->AppendChildTo(aContent, false, IgnoreErrors());
+ }
+ } else {
+ nsCOMPtr<nsIContent> parent = GetCurrentContent();
+
+ if (parent) {
+ ErrorResult rv;
+ parent->AppendChildTo(aContent, false, rv);
+ result = rv.StealNSResult();
+ }
+ }
+ return result;
+}
+
+// Create an XML parser and an XSL content sink and start parsing
+// the XSL stylesheet located at the given URI.
+nsresult nsXMLContentSink::LoadXSLStyleSheet(nsIURI* aUrl) {
+ nsCOMPtr<nsIDocumentTransformer> processor = new txMozillaXSLTProcessor();
+ mDocument->SetUseCounter(eUseCounter_custom_XSLStylesheet);
+
+ processor->SetTransformObserver(this);
+
+ if (NS_SUCCEEDED(processor->LoadStyleSheet(aUrl, mDocument))) {
+ mXSLTProcessor.swap(processor);
+ }
+
+ // Intentionally ignore errors here, we should continue loading the
+ // XML document whether we're able to load the XSLT stylesheet or
+ // not.
+
+ return NS_OK;
+}
+
+nsresult nsXMLContentSink::ProcessStyleLinkFromHeader(
+ const nsAString& aHref, bool aAlternate, const nsAString& aTitle,
+ const nsAString& aIntegrity, const nsAString& aType,
+ const nsAString& aMedia, const nsAString& aReferrerPolicy) {
+ mPrettyPrintXML = false;
+
+ nsAutoCString cmd;
+ if (mParser) GetParser()->GetCommand(cmd);
+ if (cmd.EqualsASCII(kLoadAsData))
+ return NS_OK; // Do not load stylesheets when loading as data
+
+ bool wasXSLT;
+ nsresult rv = MaybeProcessXSLTLink(nullptr, aHref, aAlternate, aType, aType,
+ aMedia, aReferrerPolicy, &wasXSLT);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (wasXSLT) {
+ // We're done here.
+ return NS_OK;
+ }
+
+ // Otherwise fall through to nsContentSink to handle CSS Link headers.
+ return nsContentSink::ProcessStyleLinkFromHeader(
+ aHref, aAlternate, aTitle, aIntegrity, aType, aMedia, aReferrerPolicy);
+}
+
+nsresult nsXMLContentSink::MaybeProcessXSLTLink(
+ ProcessingInstruction* aProcessingInstruction, const nsAString& aHref,
+ bool aAlternate, const nsAString& aTitle, const nsAString& aType,
+ const nsAString& aMedia, const nsAString& aReferrerPolicy, bool* aWasXSLT) {
+ bool wasXSLT = aType.LowerCaseEqualsLiteral(TEXT_XSL) ||
+ aType.LowerCaseEqualsLiteral(APPLICATION_XSLT_XML) ||
+ aType.LowerCaseEqualsLiteral(TEXT_XML) ||
+ aType.LowerCaseEqualsLiteral(APPLICATION_XML);
+
+ if (aWasXSLT) {
+ *aWasXSLT = wasXSLT;
+ }
+
+ if (!wasXSLT) {
+ return NS_OK;
+ }
+
+ if (aAlternate) {
+ // don't load alternate XSLT
+ return NS_OK;
+ }
+ // LoadXSLStyleSheet needs a mDocShell.
+ if (!mDocShell) {
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIURI> url;
+ nsresult rv = NS_NewURI(getter_AddRefs(url), aHref, nullptr,
+ mDocument->GetDocBaseURI());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Do security check
+ nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
+ rv = secMan->CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), url,
+ nsIScriptSecurityManager::ALLOW_CHROME,
+ mDocument->InnerWindowID());
+ NS_ENSURE_SUCCESS(rv, NS_OK);
+
+ nsCOMPtr<nsILoadInfo> secCheckLoadInfo =
+ new net::LoadInfo(mDocument->NodePrincipal(), // loading principal
+ mDocument->NodePrincipal(), // triggering principal
+ aProcessingInstruction,
+ nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
+ nsIContentPolicy::TYPE_XSLT);
+
+ // Do content policy check
+ int16_t decision = nsIContentPolicy::ACCEPT;
+ rv = NS_CheckContentLoadPolicy(url, secCheckLoadInfo,
+ NS_ConvertUTF16toUTF8(aType), &decision,
+ nsContentUtils::GetContentPolicy());
+
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (NS_CP_REJECTED(decision)) {
+ return NS_OK;
+ }
+
+ return LoadXSLStyleSheet(url);
+}
+
+void nsXMLContentSink::SetDocumentCharset(NotNull<const Encoding*> aEncoding) {
+ if (mDocument) {
+ mDocument->SetDocumentCharacterSet(aEncoding);
+ }
+}
+
+nsISupports* nsXMLContentSink::GetTarget() { return ToSupports(mDocument); }
+
+bool nsXMLContentSink::IsScriptExecuting() { return IsScriptExecutingImpl(); }
+
+nsresult nsXMLContentSink::FlushText(bool aReleaseTextNode) {
+ nsresult rv = NS_OK;
+
+ if (mTextLength != 0) {
+ if (mLastTextNode) {
+ bool notify = HaveNotifiedForCurrentContent();
+ // We could probably always increase mInNotification here since
+ // if AppendText doesn't notify it shouldn't trigger evil code.
+ // But just in case it does, we don't want to mask any notifications.
+ if (notify) {
+ ++mInNotification;
+ }
+ rv = mLastTextNode->AppendText(mText, mTextLength, notify);
+ if (notify) {
+ --mInNotification;
+ }
+
+ mTextLength = 0;
+ } else {
+ RefPtr<nsTextNode> textContent =
+ new (mNodeInfoManager) nsTextNode(mNodeInfoManager);
+
+ mLastTextNode = textContent;
+
+ // Set the text in the text node
+ textContent->SetText(mText, mTextLength, false);
+ mTextLength = 0;
+
+ // Add text to its parent
+ rv = AddContentAsLeaf(textContent);
+ }
+ }
+
+ if (aReleaseTextNode) {
+ mLastTextNode = nullptr;
+ }
+
+ return rv;
+}
+
+nsIContent* nsXMLContentSink::GetCurrentContent() {
+ if (mContentStack.Length() == 0) {
+ return nullptr;
+ }
+ return GetCurrentStackNode()->mContent;
+}
+
+nsXMLContentSink::StackNode* nsXMLContentSink::GetCurrentStackNode() {
+ int32_t count = mContentStack.Length();
+ return count != 0 ? &mContentStack[count - 1] : nullptr;
+}
+
+nsresult nsXMLContentSink::PushContent(nsIContent* aContent) {
+ MOZ_ASSERT(aContent, "Null content being pushed!");
+ StackNode* sn = mContentStack.AppendElement();
+ NS_ENSURE_TRUE(sn, NS_ERROR_OUT_OF_MEMORY);
+
+ nsIContent* contentToPush = aContent;
+
+ // When an XML parser would append a node to a template element, it
+ // must instead append it to the template element's template contents.
+ if (contentToPush->IsHTMLElement(nsGkAtoms::_template)) {
+ HTMLTemplateElement* templateElement =
+ static_cast<HTMLTemplateElement*>(contentToPush);
+ contentToPush = templateElement->Content();
+ }
+
+ sn->mContent = contentToPush;
+ sn->mNumFlushed = 0;
+ return NS_OK;
+}
+
+void nsXMLContentSink::PopContent() {
+ if (mContentStack.IsEmpty()) {
+ NS_WARNING("Popping empty stack");
+ return;
+ }
+
+ mContentStack.RemoveLastElement();
+}
+
+bool nsXMLContentSink::HaveNotifiedForCurrentContent() const {
+ uint32_t stackLength = mContentStack.Length();
+ if (stackLength) {
+ const StackNode& stackNode = mContentStack[stackLength - 1];
+ nsIContent* parent = stackNode.mContent;
+ return stackNode.mNumFlushed == parent->GetChildCount();
+ }
+ return true;
+}
+
+void nsXMLContentSink::MaybeStartLayout(bool aIgnorePendingSheets) {
+ // XXXbz if aIgnorePendingSheets is true, what should we do when
+ // mXSLTProcessor or CanStillPrettyPrint()?
+ if (mLayoutStarted || mXSLTProcessor || CanStillPrettyPrint()) {
+ return;
+ }
+ StartLayout(aIgnorePendingSheets);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+bool nsXMLContentSink::SetDocElement(int32_t aNameSpaceID, nsAtom* aTagName,
+ nsIContent* aContent) {
+ if (mDocElement) return false;
+
+ mDocElement = aContent;
+
+ if (mXSLTProcessor) {
+ mDocumentChildren.AppendElement(aContent);
+ return true;
+ }
+
+ if (!mDocumentChildren.IsEmpty()) {
+ for (nsIContent* child : mDocumentChildren) {
+ mDocument->AppendChildTo(child, false, IgnoreErrors());
+ }
+ mDocumentChildren.Clear();
+ }
+
+ // check for root elements that needs special handling for
+ // prettyprinting
+ if (aNameSpaceID == kNameSpaceID_XSLT &&
+ (aTagName == nsGkAtoms::stylesheet || aTagName == nsGkAtoms::transform)) {
+ mPrettyPrintHasSpecialRoot = true;
+ if (mPrettyPrintXML) {
+ // In this case, disable script execution, stylesheet
+ // loading, and auto XLinks since we plan to prettyprint.
+ mDocument->ScriptLoader()->SetEnabled(false);
+ if (mCSSLoader) {
+ mCSSLoader->SetEnabled(false);
+ }
+ }
+ }
+
+ IgnoredErrorResult rv;
+ mDocument->AppendChildTo(mDocElement, NotifyForDocElement(), rv);
+ if (rv.Failed()) {
+ // If we return false here, the caller will bail out because it won't
+ // find a parent content node to append to, which is fine.
+ return false;
+ }
+
+ return true;
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::HandleStartElement(const char16_t* aName,
+ const char16_t** aAtts,
+ uint32_t aAttsCount, uint32_t aLineNumber,
+ uint32_t aColumnNumber) {
+ return HandleStartElement(aName, aAtts, aAttsCount, aLineNumber,
+ aColumnNumber, true);
+}
+
+nsresult nsXMLContentSink::HandleStartElement(
+ const char16_t* aName, const char16_t** aAtts, uint32_t aAttsCount,
+ uint32_t aLineNumber, uint32_t aColumnNumber, bool aInterruptable) {
+ MOZ_ASSERT(aAttsCount % 2 == 0, "incorrect aAttsCount");
+ // Adjust aAttsCount so it's the actual number of attributes
+ aAttsCount /= 2;
+
+ nsresult result = NS_OK;
+ bool appendContent = true;
+ nsCOMPtr<nsIContent> content;
+
+ // XXX Hopefully the parser will flag this before we get
+ // here. If we're in the epilog, there should be no
+ // new elements
+ MOZ_ASSERT(eXMLContentSinkState_InEpilog != mState);
+
+ FlushText();
+ DidAddContent();
+
+ mState = eXMLContentSinkState_InDocumentElement;
+
+ int32_t nameSpaceID;
+ RefPtr<nsAtom> prefix, localName;
+ nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
+ getter_AddRefs(localName), &nameSpaceID);
+
+ if (!OnOpenContainer(aAtts, aAttsCount, nameSpaceID, localName,
+ aLineNumber)) {
+ return NS_OK;
+ }
+
+ RefPtr<mozilla::dom::NodeInfo> nodeInfo;
+ nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
+ nsINode::ELEMENT_NODE);
+
+ result = CreateElement(aAtts, aAttsCount, nodeInfo, aLineNumber,
+ aColumnNumber, getter_AddRefs(content), &appendContent,
+ FROM_PARSER_NETWORK);
+ NS_ENSURE_SUCCESS(result, result);
+
+ // Have to do this before we push the new content on the stack... and have to
+ // do that before we set attributes, call BindToTree, etc. Ideally we'd push
+ // on the stack inside CreateElement (which is effectively what the HTML sink
+ // does), but that's hard with all the subclass overrides going on.
+ nsCOMPtr<nsIContent> parent = GetCurrentContent();
+
+ result = PushContent(content);
+ NS_ENSURE_SUCCESS(result, result);
+
+ // Set the attributes on the new content element
+ result = AddAttributes(aAtts, content->AsElement());
+
+ if (NS_OK == result) {
+ // Store the element
+ if (!SetDocElement(nameSpaceID, localName, content) && appendContent) {
+ NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
+
+ parent->AppendChildTo(content, false, IgnoreErrors());
+ }
+ }
+
+ // Some HTML nodes need DoneCreatingElement() called to initialize
+ // properly (eg form state restoration).
+ if (nsIContent::RequiresDoneCreatingElement(nodeInfo->NamespaceID(),
+ nodeInfo->NameAtom())) {
+ content->DoneCreatingElement();
+ }
+
+ if (nodeInfo->NamespaceID() == kNameSpaceID_XHTML &&
+ nodeInfo->NameAtom() == nsGkAtoms::head && !mCurrentHead) {
+ mCurrentHead = content;
+ }
+
+ if (IsMonolithicContainer(nodeInfo)) {
+ mInMonolithicContainer++;
+ }
+
+ if (!mXSLTProcessor) {
+ if (content == mDocElement) {
+ nsContentUtils::AddScriptRunner(
+ new nsDocElementCreatedNotificationRunner(mDocument));
+
+ if (aInterruptable && NS_SUCCEEDED(result) && mParser &&
+ !mParser->IsParserEnabled()) {
+ return NS_ERROR_HTMLPARSER_BLOCK;
+ }
+ } else if (!mCurrentHead) {
+ // This isn't the root and we're not inside an XHTML <head>.
+ // Might need to start layout
+ MaybeStartLayout(false);
+ }
+ }
+
+ return aInterruptable && NS_SUCCEEDED(result) ? DidProcessATokenImpl()
+ : result;
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::HandleEndElement(const char16_t* aName) {
+ return HandleEndElement(aName, true);
+}
+
+nsresult nsXMLContentSink::HandleEndElement(const char16_t* aName,
+ bool aInterruptable) {
+ nsresult result = NS_OK;
+
+ // XXX Hopefully the parser will flag this before we get
+ // here. If we're in the prolog or epilog, there should be
+ // no close tags for elements.
+ MOZ_ASSERT(eXMLContentSinkState_InDocumentElement == mState);
+
+ FlushText();
+
+ StackNode* sn = GetCurrentStackNode();
+ if (!sn) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ nsCOMPtr<nsIContent> content;
+ sn->mContent.swap(content);
+ uint32_t numFlushed = sn->mNumFlushed;
+
+ PopContent();
+ NS_ASSERTION(content, "failed to pop content");
+#ifdef DEBUG
+ // Check that we're closing the right thing
+ RefPtr<nsAtom> debugNameSpacePrefix, debugTagAtom;
+ int32_t debugNameSpaceID;
+ nsContentUtils::SplitExpatName(aName, getter_AddRefs(debugNameSpacePrefix),
+ getter_AddRefs(debugTagAtom),
+ &debugNameSpaceID);
+ // Check if we are closing a template element because template
+ // elements do not get pushed on the stack, the template
+ // element content is pushed instead.
+ bool isTemplateElement = debugTagAtom == nsGkAtoms::_template &&
+ debugNameSpaceID == kNameSpaceID_XHTML;
+ NS_ASSERTION(
+ content->NodeInfo()->Equals(debugTagAtom, debugNameSpaceID) ||
+ (debugNameSpaceID == kNameSpaceID_MathML &&
+ content->NodeInfo()->NamespaceID() == kNameSpaceID_disabled_MathML &&
+ content->NodeInfo()->Equals(debugTagAtom)) ||
+ (debugNameSpaceID == kNameSpaceID_SVG &&
+ content->NodeInfo()->NamespaceID() == kNameSpaceID_disabled_SVG &&
+ content->NodeInfo()->Equals(debugTagAtom)) ||
+ isTemplateElement,
+ "Wrong element being closed");
+#endif
+
+ // Make sure to notify on our kids before we call out to any other code that
+ // might reenter us and call FlushTags, in a state in which we've already
+ // popped "content" from the stack but haven't notified on its kids yet.
+ int32_t stackLen = mContentStack.Length();
+ if (mNotifyLevel >= stackLen) {
+ if (numFlushed < content->GetChildCount()) {
+ NotifyAppend(content, numFlushed);
+ }
+ mNotifyLevel = stackLen - 1;
+ }
+
+ result = CloseElement(content);
+
+ if (mCurrentHead == content) {
+ mCurrentHead = nullptr;
+ }
+
+ if (mDocElement == content) {
+ // XXXbz for roots that don't want to be appended on open, we
+ // probably need to deal here.... (and stop appending them on open).
+ mState = eXMLContentSinkState_InEpilog;
+
+ mDocument->OnParsingCompleted();
+
+ // We might have had no occasion to start layout yet. Do so now.
+ MaybeStartLayout(false);
+ }
+
+ DidAddContent();
+
+ if (content->IsSVGElement(nsGkAtoms::svg)) {
+ FlushTags();
+ nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(content);
+ if (NS_FAILED(content->OwnerDoc()->Dispatch(TaskCategory::Other,
+ event.forget()))) {
+ NS_WARNING("failed to dispatch svg load dispatcher");
+ }
+ }
+
+ return aInterruptable && NS_SUCCEEDED(result) ? DidProcessATokenImpl()
+ : result;
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::HandleComment(const char16_t* aName) {
+ FlushText();
+
+ RefPtr<Comment> comment = new (mNodeInfoManager) Comment(mNodeInfoManager);
+ comment->SetText(nsDependentString(aName), false);
+ nsresult rv = AddContentAsLeaf(comment);
+ DidAddContent();
+
+ return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv;
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::HandleCDataSection(const char16_t* aData, uint32_t aLength) {
+ // XSLT doesn't differentiate between text and cdata and wants adjacent
+ // textnodes merged, so add as text.
+ if (mXSLTProcessor) {
+ return AddText(aData, aLength);
+ }
+
+ FlushText();
+
+ RefPtr<CDATASection> cdata =
+ new (mNodeInfoManager) CDATASection(mNodeInfoManager);
+ cdata->SetText(aData, aLength, false);
+ nsresult rv = AddContentAsLeaf(cdata);
+ DidAddContent();
+
+ return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv;
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::HandleDoctypeDecl(const nsAString& aSubset,
+ const nsAString& aName,
+ const nsAString& aSystemId,
+ const nsAString& aPublicId,
+ nsISupports* aCatalogData) {
+ FlushText();
+
+ NS_ASSERTION(mDocument, "Shouldn't get here from a document fragment");
+
+ RefPtr<nsAtom> name = NS_Atomize(aName);
+ NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
+
+ // Create a new doctype node
+ RefPtr<DocumentType> docType = NS_NewDOMDocumentType(
+ mNodeInfoManager, name, aPublicId, aSystemId, aSubset);
+
+ MOZ_ASSERT(!aCatalogData,
+ "Need to add back support for catalog style "
+ "sheets");
+
+ mDocumentChildren.AppendElement(docType);
+ DidAddContent();
+ return DidProcessATokenImpl();
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::HandleCharacterData(const char16_t* aData, uint32_t aLength) {
+ return HandleCharacterData(aData, aLength, true);
+}
+
+nsresult nsXMLContentSink::HandleCharacterData(const char16_t* aData,
+ uint32_t aLength,
+ bool aInterruptable) {
+ nsresult rv = NS_OK;
+ if (aData && mState != eXMLContentSinkState_InProlog &&
+ mState != eXMLContentSinkState_InEpilog) {
+ rv = AddText(aData, aLength);
+ }
+ return aInterruptable && NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv;
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::HandleProcessingInstruction(const char16_t* aTarget,
+ const char16_t* aData) {
+ FlushText();
+
+ const nsDependentString target(aTarget);
+ const nsDependentString data(aData);
+
+ RefPtr<ProcessingInstruction> node =
+ NS_NewXMLProcessingInstruction(mNodeInfoManager, target, data);
+
+ auto* linkStyle = LinkStyle::FromNode(*node);
+ if (linkStyle) {
+ linkStyle->SetEnableUpdates(false);
+ mPrettyPrintXML = false;
+ }
+
+ nsresult rv = AddContentAsLeaf(node);
+ NS_ENSURE_SUCCESS(rv, rv);
+ DidAddContent();
+
+ if (linkStyle) {
+ // This is an xml-stylesheet processing instruction... but it might not be
+ // a CSS one if the type is set to something else.
+ linkStyle->SetEnableUpdates(true);
+ auto updateOrError =
+ linkStyle->UpdateStyleSheet(mRunsToCompletion ? nullptr : this);
+ if (updateOrError.isErr()) {
+ return updateOrError.unwrapErr();
+ }
+
+ auto update = updateOrError.unwrap();
+ if (update.WillNotify()) {
+ // Successfully started a stylesheet load
+ if (update.ShouldBlock() && !mRunsToCompletion) {
+ ++mPendingSheetCount;
+ mScriptLoader->AddParserBlockingScriptExecutionBlocker();
+ }
+ return NS_OK;
+ }
+ }
+
+ // Check whether this is a CSS stylesheet PI. Make sure the type
+ // handling here matches
+ // XMLStylesheetProcessingInstruction::GetStyleSheetInfo.
+ nsAutoString type;
+ nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type);
+ nsAutoString mimeType, notUsed;
+ nsContentUtils::SplitMimeType(type, mimeType, notUsed);
+
+ if (mState != eXMLContentSinkState_InProlog ||
+ !target.EqualsLiteral("xml-stylesheet") || mimeType.IsEmpty() ||
+ mimeType.LowerCaseEqualsLiteral("text/css")) {
+ // Either not a useful stylesheet PI, or a CSS stylesheet PI that
+ // got handled above by the "ssle" bits. We're done here.
+ return DidProcessATokenImpl();
+ }
+
+ // If it's not a CSS stylesheet PI...
+ nsAutoString href, title, media;
+ bool isAlternate = false;
+
+ // If there was no href, we can't do anything with this PI
+ if (!ParsePIData(data, href, title, media, isAlternate)) {
+ return DidProcessATokenImpl();
+ }
+
+ // <?xml-stylesheet?> processing instructions don't have a referrerpolicy
+ // pseudo-attribute, so we pass in an empty string
+ rv =
+ MaybeProcessXSLTLink(node, href, isAlternate, title, type, media, u""_ns);
+ return NS_SUCCEEDED(rv) ? DidProcessATokenImpl() : rv;
+}
+
+/* static */
+bool nsXMLContentSink::ParsePIData(const nsString& aData, nsString& aHref,
+ nsString& aTitle, nsString& aMedia,
+ bool& aIsAlternate) {
+ // If there was no href, we can't do anything with this PI
+ if (!nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::href, aHref)) {
+ return false;
+ }
+
+ nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::title, aTitle);
+
+ nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::media, aMedia);
+
+ nsAutoString alternate;
+ nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::alternate,
+ alternate);
+
+ aIsAlternate = alternate.EqualsLiteral("yes");
+
+ return true;
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::HandleXMLDeclaration(const char16_t* aVersion,
+ const char16_t* aEncoding,
+ int32_t aStandalone) {
+ mDocument->SetXMLDeclaration(aVersion, aEncoding, aStandalone);
+
+ return DidProcessATokenImpl();
+}
+
+NS_IMETHODIMP
+nsXMLContentSink::ReportError(const char16_t* aErrorText,
+ const char16_t* aSourceText,
+ nsIScriptError* aError, bool* _retval) {
+ MOZ_ASSERT(aError && aSourceText && aErrorText, "Check arguments!!!");
+ nsresult rv = NS_OK;
+
+ // The expat driver should report the error. We're just cleaning up the mess.
+ *_retval = true;
+
+ mPrettyPrintXML = false;
+
+ mState = eXMLContentSinkState_InProlog;
+
+ // XXX need to stop scripts here -- hsivonen
+
+ // stop observing in order to avoid crashing when removing content
+ mDocument->RemoveObserver(this);
+ mIsDocumentObserver = false;
+
+ // Clear the current content
+ mDocumentChildren.Clear();
+ while (mDocument->GetLastChild()) {
+ mDocument->GetLastChild()->Remove();
+ }
+ mDocElement = nullptr;
+
+ // Clear any buffered-up text we have. It's enough to set the length to 0.
+ // The buffer itself is allocated when we're created and deleted in our
+ // destructor, so don't mess with it.
+ mTextLength = 0;
+
+ if (mXSLTProcessor) {
+ // Get rid of the XSLT processor.
+ mXSLTProcessor->CancelLoads();
+ mXSLTProcessor = nullptr;
+ }
+
+ // release the nodes on stack
+ mContentStack.Clear();
+ mNotifyLevel = 0;
+
+ // return leaving the document empty if we're asked to not add a <parsererror>
+ // root node
+ if (mDocument->SuppressParserErrorElement()) {
+ return NS_OK;
+ }
+
+ // prepare to set <parsererror> as the document root
+ rv = HandleProcessingInstruction(
+ u"xml-stylesheet",
+ u"href=\"chrome://global/locale/intl.css\" type=\"text/css\"");
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ const char16_t* noAtts[] = {0, 0};
+
+ constexpr auto errorNs =
+ u"http://www.mozilla.org/newlayout/xml/parsererror.xml"_ns;
+
+ nsAutoString parsererror(errorNs);
+ parsererror.Append((char16_t)0xFFFF);
+ parsererror.AppendLiteral("parsererror");
+
+ rv = HandleStartElement(parsererror.get(), noAtts, 0, (uint32_t)-1, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = HandleCharacterData(aErrorText, NS_strlen(aErrorText), false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoString sourcetext(errorNs);
+ sourcetext.Append((char16_t)0xFFFF);
+ sourcetext.AppendLiteral("sourcetext");
+
+ rv = HandleStartElement(sourcetext.get(), noAtts, 0, (uint32_t)-1, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = HandleCharacterData(aSourceText, NS_strlen(aSourceText), false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = HandleEndElement(sourcetext.get(), false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = HandleEndElement(parsererror.get(), false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ FlushTags();
+
+ return NS_OK;
+}
+
+nsresult nsXMLContentSink::AddAttributes(const char16_t** aAtts,
+ Element* aContent) {
+ // Add tag attributes to the content attributes
+ RefPtr<nsAtom> prefix, localName;
+ while (*aAtts) {
+ int32_t nameSpaceID;
+ nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
+ getter_AddRefs(localName), &nameSpaceID);
+
+ // Add attribute to content
+ aContent->SetAttr(nameSpaceID, localName, prefix,
+ nsDependentString(aAtts[1]), false);
+ aAtts += 2;
+ }
+
+ return NS_OK;
+}
+
+#define NS_ACCUMULATION_BUFFER_SIZE 4096
+
+nsresult nsXMLContentSink::AddText(const char16_t* aText, int32_t aLength) {
+ // Copy data from string into our buffer; flush buffer when it fills up.
+ int32_t offset = 0;
+ while (0 != aLength) {
+ int32_t amount = NS_ACCUMULATION_BUFFER_SIZE - mTextLength;
+ if (0 == amount) {
+ nsresult rv = FlushText(false);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ MOZ_ASSERT(mTextLength == 0);
+ amount = NS_ACCUMULATION_BUFFER_SIZE;
+ }
+
+ if (amount > aLength) {
+ amount = aLength;
+ }
+ memcpy(&mText[mTextLength], &aText[offset], sizeof(char16_t) * amount);
+ mTextLength += amount;
+ offset += amount;
+ aLength -= amount;
+ }
+
+ return NS_OK;
+}
+
+void nsXMLContentSink::InitialTranslationCompleted() { StartLayout(false); }
+
+void nsXMLContentSink::FlushPendingNotifications(FlushType aType) {
+ // Only flush tags if we're not doing the notification ourselves
+ // (since we aren't reentrant)
+ if (!mInNotification) {
+ if (mIsDocumentObserver) {
+ // Only flush if we're still a document observer (so that our child
+ // counts should be correct).
+ if (aType >= FlushType::ContentAndNotify) {
+ FlushTags();
+ } else {
+ FlushText(false);
+ }
+ }
+ if (aType >= FlushType::EnsurePresShellInitAndFrames) {
+ // Make sure that layout has started so that the reflow flush
+ // will actually happen.
+ MaybeStartLayout(true);
+ }
+ }
+}
+
+/**
+ * NOTE!! Forked from SinkContext. Please keep in sync.
+ *
+ * Flush all elements that have been seen so far such that
+ * they are visible in the tree. Specifically, make sure
+ * that they are all added to their respective parents.
+ * Also, do notification at the top for all content that
+ * has been newly added so that the frame tree is complete.
+ */
+nsresult nsXMLContentSink::FlushTags() {
+ mDeferredFlushTags = false;
+ uint32_t oldUpdates = mUpdatesInNotification;
+
+ mUpdatesInNotification = 0;
+ ++mInNotification;
+ {
+ // Scope so we call EndUpdate before we decrease mInNotification
+ mozAutoDocUpdate updateBatch(mDocument, true);
+
+ // Don't release last text node in case we need to add to it again
+ FlushText(false);
+
+ // Start from the base of the stack (growing downward) and do
+ // a notification from the node that is closest to the root of
+ // tree for any content that has been added.
+
+ int32_t stackPos;
+ int32_t stackLen = mContentStack.Length();
+ bool flushed = false;
+ uint32_t childCount;
+ nsIContent* content;
+
+ for (stackPos = 0; stackPos < stackLen; ++stackPos) {
+ content = mContentStack[stackPos].mContent;
+ childCount = content->GetChildCount();
+
+ if (!flushed && (mContentStack[stackPos].mNumFlushed < childCount)) {
+ NotifyAppend(content, mContentStack[stackPos].mNumFlushed);
+ flushed = true;
+ }
+
+ mContentStack[stackPos].mNumFlushed = childCount;
+ }
+ mNotifyLevel = stackLen - 1;
+ }
+ --mInNotification;
+
+ if (mUpdatesInNotification > 1) {
+ UpdateChildCounts();
+ }
+
+ mUpdatesInNotification = oldUpdates;
+ return NS_OK;
+}
+
+/**
+ * NOTE!! Forked from SinkContext. Please keep in sync.
+ */
+void nsXMLContentSink::UpdateChildCounts() {
+ // Start from the top of the stack (growing upwards) and see if any
+ // new content has been appended. If so, we recognize that reflows
+ // have been generated for it and we should make sure that no
+ // further reflows occur. Note that we have to include stackPos == 0
+ // to properly notify on kids of <html>.
+ int32_t stackLen = mContentStack.Length();
+ int32_t stackPos = stackLen - 1;
+ while (stackPos >= 0) {
+ StackNode& node = mContentStack[stackPos];
+ node.mNumFlushed = node.mContent->GetChildCount();
+
+ stackPos--;
+ }
+ mNotifyLevel = stackLen - 1;
+}
+
+bool nsXMLContentSink::IsMonolithicContainer(
+ mozilla::dom::NodeInfo* aNodeInfo) {
+ return ((aNodeInfo->NamespaceID() == kNameSpaceID_XHTML &&
+ (aNodeInfo->NameAtom() == nsGkAtoms::tr ||
+ aNodeInfo->NameAtom() == nsGkAtoms::select ||
+ aNodeInfo->NameAtom() == nsGkAtoms::object)) ||
+ (aNodeInfo->NamespaceID() == kNameSpaceID_MathML &&
+ (aNodeInfo->NameAtom() == nsGkAtoms::math)));
+}
+
+void nsXMLContentSink::ContinueInterruptedParsingIfEnabled() {
+ if (mParser && mParser->IsParserEnabled()) {
+ GetParser()->ContinueInterruptedParsing();
+ }
+}
+
+void nsXMLContentSink::ContinueInterruptedParsingAsync() {
+ nsCOMPtr<nsIRunnable> ev = NewRunnableMethod(
+ "nsXMLContentSink::ContinueInterruptedParsingIfEnabled", this,
+ &nsXMLContentSink::ContinueInterruptedParsingIfEnabled);
+
+ mDocument->Dispatch(mozilla::TaskCategory::Other, ev.forget());
+}
+
+nsIParser* nsXMLContentSink::GetParser() {
+ return static_cast<nsIParser*>(mParser.get());
+}
diff --git a/dom/xml/nsXMLContentSink.h b/dom/xml/nsXMLContentSink.h
new file mode 100644
index 0000000000..41acbbc027
--- /dev/null
+++ b/dom/xml/nsXMLContentSink.h
@@ -0,0 +1,217 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsXMLContentSink_h__
+#define nsXMLContentSink_h__
+
+#include "mozilla/Attributes.h"
+#include "nsContentSink.h"
+#include "nsIXMLContentSink.h"
+#include "nsIExpatSink.h"
+#include "nsIDocumentTransformer.h"
+#include "nsTArray.h"
+#include "nsCOMPtr.h"
+#include "nsCRT.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsIDTD.h"
+#include "mozilla/dom/FromParser.h"
+
+class nsIURI;
+class nsIContent;
+class nsIParser;
+class nsTextNode;
+
+namespace mozilla::dom {
+class NodeInfo;
+class ProcessingInstruction;
+} // namespace mozilla::dom
+
+enum XMLContentSinkState {
+ eXMLContentSinkState_InProlog,
+ eXMLContentSinkState_InDocumentElement,
+ eXMLContentSinkState_InEpilog
+};
+
+class nsXMLContentSink : public nsContentSink,
+ public nsIXMLContentSink,
+ public nsITransformObserver,
+ public nsIExpatSink {
+ public:
+ struct StackNode {
+ nsCOMPtr<nsIContent> mContent;
+ uint32_t mNumFlushed;
+ };
+
+ nsXMLContentSink();
+
+ nsresult Init(mozilla::dom::Document* aDoc, nsIURI* aURL,
+ nsISupports* aContainer, nsIChannel* aChannel);
+
+ // nsISupports
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLContentSink, nsContentSink)
+
+ NS_DECL_NSIEXPATSINK
+
+ // nsIContentSink
+ NS_IMETHOD WillParse(void) override;
+ NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) override;
+ NS_IMETHOD DidBuildModel(bool aTerminated) override;
+ NS_IMETHOD WillInterrupt(void) override;
+ void WillResume() override;
+ NS_IMETHOD SetParser(nsParserBase* aParser) override;
+ virtual void InitialTranslationCompleted() override;
+ virtual void FlushPendingNotifications(mozilla::FlushType aType) override;
+ virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override;
+ virtual nsISupports* GetTarget() override;
+ virtual bool IsScriptExecuting() override;
+ virtual void ContinueInterruptedParsingAsync() override;
+ bool IsPrettyPrintXML() const override { return mPrettyPrintXML; }
+ bool IsPrettyPrintHasSpecialRoot() const override {
+ return mPrettyPrintHasSpecialRoot;
+ }
+
+ // nsITransformObserver
+ nsresult OnDocumentCreated(mozilla::dom::Document* aSourceDocument,
+ mozilla::dom::Document* aResultDocument) override;
+ nsresult OnTransformDone(mozilla::dom::Document* aSourceDocument,
+ nsresult aResult,
+ mozilla::dom::Document* aResultDocument) override;
+
+ // nsICSSLoaderObserver
+ NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheet* aSheet, bool aWasDeferred,
+ nsresult aStatus) override;
+ static bool ParsePIData(const nsString& aData, nsString& aHref,
+ nsString& aTitle, nsString& aMedia,
+ bool& aIsAlternate);
+
+ protected:
+ virtual ~nsXMLContentSink();
+
+ nsIParser* GetParser();
+
+ void ContinueInterruptedParsingIfEnabled();
+
+ // Start layout. If aIgnorePendingSheets is true, this will happen even if
+ // we still have stylesheet loads pending. Otherwise, we'll wait until the
+ // stylesheets are all done loading.
+ virtual void MaybeStartLayout(bool aIgnorePendingSheets);
+
+ virtual nsresult AddAttributes(const char16_t** aNode,
+ mozilla::dom::Element* aElement);
+ nsresult AddText(const char16_t* aString, int32_t aLength);
+
+ virtual bool OnOpenContainer(const char16_t** aAtts, uint32_t aAttsCount,
+ int32_t aNameSpaceID, nsAtom* aTagName,
+ uint32_t aLineNumber) {
+ return true;
+ }
+ // Set the given content as the root element for the created document
+ // don't set if root element was already set.
+ // return TRUE if this call set the root element
+ virtual bool SetDocElement(int32_t aNameSpaceID, nsAtom* aTagName,
+ nsIContent* aContent);
+ virtual bool NotifyForDocElement() { return true; }
+ virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
+ mozilla::dom::NodeInfo* aNodeInfo,
+ uint32_t aLineNumber, uint32_t aColumnNumber,
+ nsIContent** aResult, bool* aAppendContent,
+ mozilla::dom::FromParser aFromParser);
+
+ // aParent is allowed to be null here if this is the root content
+ // being closed
+ virtual nsresult CloseElement(nsIContent* aContent);
+
+ virtual nsresult FlushText(bool aReleaseTextNode = true);
+
+ nsresult AddContentAsLeaf(nsIContent* aContent);
+
+ nsIContent* GetCurrentContent();
+ StackNode* GetCurrentStackNode();
+ nsresult PushContent(nsIContent* aContent);
+ void PopContent();
+ bool HaveNotifiedForCurrentContent() const;
+
+ nsresult FlushTags() override;
+
+ void UpdateChildCounts() override;
+
+ void DidAddContent() {
+ if (!mXSLTProcessor && IsTimeToNotify()) {
+ FlushTags();
+ }
+ }
+
+ // nsContentSink override
+ virtual nsresult ProcessStyleLinkFromHeader(
+ const nsAString& aHref, bool aAlternate, const nsAString& aTitle,
+ const nsAString& aIntegrity, const nsAString& aType,
+ const nsAString& aMedia, const nsAString& aReferrerPolicy) override;
+
+ // Try to handle an XSLT style link. If NS_OK is returned and aWasXSLT is not
+ // null, *aWasXSLT will be set to whether we processed this link as XSLT.
+ //
+ // aProcessingInstruction can be null if this information comes from a Link
+ // header; otherwise it will be the xml-styleshset XML PI that the loading
+ // information comes from.
+ virtual nsresult MaybeProcessXSLTLink(
+ mozilla::dom::ProcessingInstruction* aProcessingInstruction,
+ const nsAString& aHref, bool aAlternate, const nsAString& aTitle,
+ const nsAString& aType, const nsAString& aMedia,
+ const nsAString& aReferrerPolicy, bool* aWasXSLT = nullptr);
+
+ nsresult LoadXSLStyleSheet(nsIURI* aUrl);
+
+ bool CanStillPrettyPrint();
+
+ nsresult MaybePrettyPrint();
+
+ bool IsMonolithicContainer(mozilla::dom::NodeInfo* aNodeInfo);
+
+ nsresult HandleStartElement(const char16_t* aName, const char16_t** aAtts,
+ uint32_t aAttsCount, uint32_t aLineNumber,
+ uint32_t aColumnNumber, bool aInterruptable);
+ nsresult HandleEndElement(const char16_t* aName, bool aInterruptable);
+ nsresult HandleCharacterData(const char16_t* aData, uint32_t aLength,
+ bool aInterruptable);
+
+ nsCOMPtr<nsIContent> mDocElement;
+ nsCOMPtr<nsIContent> mCurrentHead; // When set, we're in an XHTML <haed>
+
+ XMLContentSinkState mState;
+
+ // The length of the valid data in mText.
+ int32_t mTextLength;
+
+ int32_t mNotifyLevel;
+ RefPtr<nsTextNode> mLastTextNode;
+
+ uint8_t mPrettyPrintXML : 1;
+ uint8_t mPrettyPrintHasSpecialRoot : 1;
+ uint8_t mPrettyPrintHasFactoredElements : 1;
+ uint8_t mPrettyPrinting : 1; // True if we called PrettyPrint() and it
+ // decided we should in fact prettyprint.
+ // True to call prevent script execution in the fragment mode.
+ uint8_t mPreventScriptExecution : 1;
+
+ nsTArray<StackNode> mContentStack;
+
+ nsCOMPtr<nsIDocumentTransformer> mXSLTProcessor;
+
+ // Holds the children in the prolog until the root element is added, after
+ // which they're inserted in the document. However, if we're doing an XSLT
+ // transform this will actually hold all the children of the source document,
+ // until the transform is finished. After the transform is finished we'll just
+ // discard the children.
+ nsTArray<nsCOMPtr<nsIContent>> mDocumentChildren;
+
+ static const int NS_ACCUMULATION_BUFFER_SIZE = 4096;
+ // Our currently accumulated text that we have not flushed to a textnode yet.
+ char16_t mText[NS_ACCUMULATION_BUFFER_SIZE];
+};
+
+#endif // nsXMLContentSink_h__
diff --git a/dom/xml/nsXMLElement.cpp b/dom/xml/nsXMLElement.cpp
new file mode 100644
index 0000000000..ef51715d1b
--- /dev/null
+++ b/dom/xml/nsXMLElement.cpp
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsXMLElement.h"
+#include "mozilla/dom/ElementBinding.h"
+#include "mozilla/dom/ElementInlines.h"
+#include "nsContentUtils.h" // nsAutoScriptBlocker
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+nsresult NS_NewXMLElement(
+ Element** aInstancePtrResult,
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo) {
+ RefPtr<mozilla::dom::NodeInfo> nodeInfo(std::move(aNodeInfo));
+ auto* nim = nodeInfo->NodeInfoManager();
+ RefPtr<nsXMLElement> it = new (nim) nsXMLElement(nodeInfo.forget());
+
+ it.forget(aInstancePtrResult);
+ return NS_OK;
+}
+
+JSObject* nsXMLElement::WrapNode(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) {
+ return Element_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+void nsXMLElement::UnbindFromTree(bool aNullParent) {
+ nsAtom* property;
+ switch (GetPseudoElementType()) {
+ case PseudoStyleType::marker:
+ property = nsGkAtoms::markerPseudoProperty;
+ break;
+ case PseudoStyleType::before:
+ property = nsGkAtoms::beforePseudoProperty;
+ break;
+ case PseudoStyleType::after:
+ property = nsGkAtoms::afterPseudoProperty;
+ break;
+ default:
+ property = nullptr;
+ }
+ if (property) {
+ MOZ_ASSERT(GetParent());
+ MOZ_ASSERT(GetParent()->IsElement());
+ GetParent()->RemoveProperty(property);
+ }
+ Element::UnbindFromTree(aNullParent);
+}
+
+NS_IMPL_ELEMENT_CLONE(nsXMLElement)
diff --git a/dom/xml/nsXMLElement.h b/dom/xml/nsXMLElement.h
new file mode 100644
index 0000000000..e401965fff
--- /dev/null
+++ b/dom/xml/nsXMLElement.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsXMLElement_h___
+#define nsXMLElement_h___
+
+#include "mozilla/Attributes.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/DOMRect.h"
+
+class nsXMLElement : public mozilla::dom::Element {
+ public:
+ explicit nsXMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
+ : mozilla::dom::Element(std::move(aNodeInfo)) {}
+
+ // nsISupports
+ NS_INLINE_DECL_REFCOUNTING_INHERITED(nsXMLElement, mozilla::dom::Element)
+
+ // nsINode interface methods
+ virtual nsresult Clone(mozilla::dom::NodeInfo*,
+ nsINode** aResult) const override;
+
+ virtual void UnbindFromTree(bool aNullParent = true) override;
+
+ protected:
+ virtual ~nsXMLElement() = default;
+
+ virtual JSObject* WrapNode(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) override;
+};
+
+#endif // nsXMLElement_h___
diff --git a/dom/xml/nsXMLFragmentContentSink.cpp b/dom/xml/nsXMLFragmentContentSink.cpp
new file mode 100644
index 0000000000..ddf96793e4
--- /dev/null
+++ b/dom/xml/nsXMLFragmentContentSink.cpp
@@ -0,0 +1,372 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsCOMPtr.h"
+#include "nsXMLContentSink.h"
+#include "nsIFragmentContentSink.h"
+#include "nsIXMLContentSink.h"
+#include "nsContentSink.h"
+#include "nsIExpatSink.h"
+#include "nsIDTD.h"
+#include "mozilla/dom/Document.h"
+#include "nsIContent.h"
+#include "nsGkAtoms.h"
+#include "mozilla/dom/NodeInfo.h"
+#include "nsContentCreatorFunctions.h"
+#include "nsError.h"
+#include "nsIDocShell.h"
+#include "nsIScriptError.h"
+#include "nsTHashtable.h"
+#include "nsHashKeys.h"
+#include "nsTArray.h"
+#include "nsCycleCollectionParticipant.h"
+#include "mozilla/css/Loader.h"
+#include "mozilla/dom/DocumentFragment.h"
+#include "mozilla/dom/ProcessingInstruction.h"
+#include "mozilla/dom/ScriptLoader.h"
+
+using namespace mozilla::dom;
+
+class nsXMLFragmentContentSink : public nsXMLContentSink,
+ public nsIFragmentContentSink {
+ public:
+ nsXMLFragmentContentSink();
+
+ // nsISupports
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLFragmentContentSink,
+ nsXMLContentSink)
+
+ // nsIExpatSink
+ NS_IMETHOD HandleDoctypeDecl(const nsAString& aSubset, const nsAString& aName,
+ const nsAString& aSystemId,
+ const nsAString& aPublicId,
+ nsISupports* aCatalogData) override;
+ NS_IMETHOD HandleProcessingInstruction(const char16_t* aTarget,
+ const char16_t* aData) override;
+ NS_IMETHOD HandleXMLDeclaration(const char16_t* aVersion,
+ const char16_t* aEncoding,
+ int32_t aStandalone) override;
+ NS_IMETHOD ReportError(const char16_t* aErrorText,
+ const char16_t* aSourceText, nsIScriptError* aError,
+ bool* aRetval) override;
+
+ // nsIContentSink
+ NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) override;
+ NS_IMETHOD DidBuildModel(bool aTerminated) override;
+ virtual void SetDocumentCharset(NotNull<const Encoding*> aEncoding) override;
+ virtual nsISupports* GetTarget() override;
+ NS_IMETHOD DidProcessATokenImpl();
+
+ // nsIXMLContentSink
+
+ // nsIFragmentContentSink
+ NS_IMETHOD FinishFragmentParsing(DocumentFragment** aFragment) override;
+ NS_IMETHOD SetTargetDocument(Document* aDocument) override;
+ NS_IMETHOD WillBuildContent() override;
+ NS_IMETHOD DidBuildContent() override;
+ NS_IMETHOD IgnoreFirstContainer() override;
+ NS_IMETHOD SetPreventScriptExecution(bool aPreventScriptExecution) override;
+
+ protected:
+ virtual ~nsXMLFragmentContentSink();
+
+ virtual bool SetDocElement(int32_t aNameSpaceID, nsAtom* aTagName,
+ nsIContent* aContent) override;
+ virtual nsresult CreateElement(const char16_t** aAtts, uint32_t aAttsCount,
+ mozilla::dom::NodeInfo* aNodeInfo,
+ uint32_t aLineNumber, uint32_t aColumnNumber,
+ nsIContent** aResult, bool* aAppendContent,
+ mozilla::dom::FromParser aFromParser) override;
+ virtual nsresult CloseElement(nsIContent* aContent) override;
+
+ virtual void MaybeStartLayout(bool aIgnorePendingSheets) override;
+
+ // nsContentSink overrides
+ virtual nsresult ProcessStyleLinkFromHeader(
+ const nsAString& aHref, bool aAlternate, const nsAString& aTitle,
+ const nsAString& aIntegrity, const nsAString& aType,
+ const nsAString& aMedia, const nsAString& aReferrerPolicy) override;
+
+ // nsXMLContentSink overrides
+ virtual nsresult MaybeProcessXSLTLink(
+ ProcessingInstruction* aProcessingInstruction, const nsAString& aHref,
+ bool aAlternate, const nsAString& aTitle, const nsAString& aType,
+ const nsAString& aMedia, const nsAString& aReferrerPolicy,
+ bool* aWasXSLT = nullptr) override;
+
+ nsCOMPtr<Document> mTargetDocument;
+ // the fragment
+ RefPtr<DocumentFragment> mRoot;
+ bool mParseError;
+};
+
+static nsresult NewXMLFragmentContentSinkHelper(
+ nsIFragmentContentSink** aResult) {
+ nsXMLFragmentContentSink* it = new nsXMLFragmentContentSink();
+
+ NS_ADDREF(*aResult = it);
+
+ return NS_OK;
+}
+
+nsresult NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aResult) {
+ return NewXMLFragmentContentSinkHelper(aResult);
+}
+
+nsXMLFragmentContentSink::nsXMLFragmentContentSink() : mParseError(false) {
+ mRunsToCompletion = true;
+}
+
+nsXMLFragmentContentSink::~nsXMLFragmentContentSink() = default;
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLFragmentContentSink)
+ NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink)
+NS_INTERFACE_MAP_END_INHERITING(nsXMLContentSink)
+
+NS_IMPL_ADDREF_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
+NS_IMPL_RELEASE_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink,
+ mTargetDocument, mRoot)
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::WillBuildModel(nsDTDMode aDTDMode) {
+ if (mRoot) {
+ return NS_OK;
+ }
+
+ mState = eXMLContentSinkState_InDocumentElement;
+
+ NS_ASSERTION(mTargetDocument, "Need a document!");
+
+ mRoot = new (mNodeInfoManager) DocumentFragment(mNodeInfoManager);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::DidBuildModel(bool aTerminated) {
+ // Drop our reference to the parser to get rid of a circular
+ // reference.
+ mParser = nullptr;
+
+ return NS_OK;
+}
+
+void nsXMLFragmentContentSink::SetDocumentCharset(
+ NotNull<const Encoding*> aEncoding) {
+ MOZ_ASSERT_UNREACHABLE("fragments shouldn't set charset");
+}
+
+nsISupports* nsXMLFragmentContentSink::GetTarget() {
+ return ToSupports(mTargetDocument);
+}
+
+////////////////////////////////////////////////////////////////////////
+
+bool nsXMLFragmentContentSink::SetDocElement(int32_t aNameSpaceID,
+ nsAtom* aTagName,
+ nsIContent* aContent) {
+ // this is a fragment, not a document
+ return false;
+}
+
+nsresult nsXMLFragmentContentSink::CreateElement(
+ const char16_t** aAtts, uint32_t aAttsCount,
+ mozilla::dom::NodeInfo* aNodeInfo, uint32_t aLineNumber,
+ uint32_t aColumnNumber, nsIContent** aResult, bool* aAppendContent,
+ FromParser /*aFromParser*/) {
+ // Claim to not be coming from parser, since we don't do any of the
+ // fancy CloseElement stuff.
+ nsresult rv = nsXMLContentSink::CreateElement(
+ aAtts, aAttsCount, aNodeInfo, aLineNumber, aColumnNumber, aResult,
+ aAppendContent, NOT_FROM_PARSER);
+
+ // When we aren't grabbing all of the content we, never open a doc
+ // element, we run into trouble on the first element, so we don't append,
+ // and simply push this onto the content stack.
+ if (mContentStack.Length() == 0) {
+ *aAppendContent = false;
+ }
+
+ return rv;
+}
+
+nsresult nsXMLFragmentContentSink::CloseElement(nsIContent* aContent) {
+ // don't do fancy stuff in nsXMLContentSink
+ if (mPreventScriptExecution && (aContent->IsHTMLElement(nsGkAtoms::script) ||
+ aContent->IsSVGElement(nsGkAtoms::script))) {
+ nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aContent);
+ if (sele) {
+ sele->PreventExecution();
+ } else {
+ NS_ASSERTION(nsNameSpaceManager::GetInstance()->mSVGDisabled,
+ "Script did QI correctly, but wasn't a disabled SVG!");
+ }
+ }
+ return NS_OK;
+}
+
+void nsXMLFragmentContentSink::MaybeStartLayout(bool aIgnorePendingSheets) {}
+
+////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::HandleDoctypeDecl(const nsAString& aSubset,
+ const nsAString& aName,
+ const nsAString& aSystemId,
+ const nsAString& aPublicId,
+ nsISupports* aCatalogData) {
+ MOZ_ASSERT_UNREACHABLE("fragments shouldn't have doctype declarations");
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::HandleProcessingInstruction(const char16_t* aTarget,
+ const char16_t* aData) {
+ FlushText();
+
+ const nsDependentString target(aTarget);
+ const nsDependentString data(aData);
+
+ RefPtr<ProcessingInstruction> node =
+ NS_NewXMLProcessingInstruction(mNodeInfoManager, target, data);
+
+ // no special processing here. that should happen when the fragment moves
+ // into the document
+ return AddContentAsLeaf(node);
+}
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::HandleXMLDeclaration(const char16_t* aVersion,
+ const char16_t* aEncoding,
+ int32_t aStandalone) {
+ MOZ_ASSERT_UNREACHABLE("fragments shouldn't have XML declarations");
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::ReportError(const char16_t* aErrorText,
+ const char16_t* aSourceText,
+ nsIScriptError* aError, bool* _retval) {
+ MOZ_ASSERT(aError && aSourceText && aErrorText, "Check arguments!!!");
+
+ // The expat driver should report the error.
+ *_retval = true;
+
+ mParseError = true;
+
+#ifdef DEBUG
+ // Report the error to stderr.
+ fprintf(stderr, "\n%s\n%s\n\n", NS_LossyConvertUTF16toASCII(aErrorText).get(),
+ NS_LossyConvertUTF16toASCII(aSourceText).get());
+#endif
+
+ // The following code is similar to the cleanup in
+ // nsXMLContentSink::ReportError()
+ mState = eXMLContentSinkState_InProlog;
+
+ // Clear the current content
+ while (mRoot->GetLastChild()) {
+ mRoot->GetLastChild()->Remove();
+ }
+
+ // Clear any buffered-up text we have. It's enough to set the length to 0.
+ // The buffer itself is allocated when we're created and deleted in our
+ // destructor, so don't mess with it.
+ mTextLength = 0;
+
+ return NS_OK;
+}
+
+nsresult nsXMLFragmentContentSink::ProcessStyleLinkFromHeader(
+ const nsAString& aHref, bool aAlternate, const nsAString& aTitle,
+ const nsAString& aIntegrity, const nsAString& aType,
+ const nsAString& aMedia, const nsAString& aReferrerPolicy)
+
+{
+ MOZ_ASSERT_UNREACHABLE("Shouldn't have headers for a fragment sink");
+ return NS_OK;
+}
+
+nsresult nsXMLFragmentContentSink::MaybeProcessXSLTLink(
+ ProcessingInstruction* aProcessingInstruction, const nsAString& aHref,
+ bool aAlternate, const nsAString& aTitle, const nsAString& aType,
+ const nsAString& aMedia, const nsAString& aReferrerPolicy, bool* aWasXSLT) {
+ MOZ_ASSERT(!aWasXSLT, "Our one caller doesn't care about whether we're XSLT");
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::FinishFragmentParsing(DocumentFragment** aFragment) {
+ mTargetDocument = nullptr;
+ mNodeInfoManager = nullptr;
+ mScriptLoader = nullptr;
+ mCSSLoader = nullptr;
+ mContentStack.Clear();
+ mDocumentURI = nullptr;
+ mDocShell = nullptr;
+ mDocElement = nullptr;
+ mCurrentHead = nullptr;
+ if (mParseError) {
+ // XXX PARSE_ERR from DOM3 Load and Save would be more appropriate
+ mRoot = nullptr;
+ mParseError = false;
+ *aFragment = nullptr;
+ return NS_ERROR_DOM_SYNTAX_ERR;
+ }
+
+ mRoot.forget(aFragment);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::SetTargetDocument(Document* aTargetDocument) {
+ NS_ENSURE_ARG_POINTER(aTargetDocument);
+
+ mTargetDocument = aTargetDocument;
+ mNodeInfoManager = aTargetDocument->NodeInfoManager();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::WillBuildContent() {
+ PushContent(mRoot);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::DidBuildContent() {
+ // Note: we need to FlushText() here because if we don't, we might not get
+ // an end element to do it for us, so make sure.
+ if (!mParseError) {
+ FlushText();
+ }
+ PopContent();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::DidProcessATokenImpl() { return NS_OK; }
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::IgnoreFirstContainer() {
+ MOZ_ASSERT_UNREACHABLE("XML isn't as broken as HTML");
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsXMLFragmentContentSink::SetPreventScriptExecution(bool aPrevent) {
+ mPreventScriptExecution = aPrevent;
+ return NS_OK;
+}
diff --git a/dom/xml/nsXMLPrettyPrinter.cpp b/dom/xml/nsXMLPrettyPrinter.cpp
new file mode 100644
index 0000000000..4a386e92fb
--- /dev/null
+++ b/dom/xml/nsXMLPrettyPrinter.cpp
@@ -0,0 +1,189 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsXMLPrettyPrinter.h"
+#include "nsContentUtils.h"
+#include "nsICSSDeclaration.h"
+#include "nsSyncLoadService.h"
+#include "nsPIDOMWindow.h"
+#include "nsNetUtil.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/ShadowRoot.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/dom/Document.h"
+#include "nsVariant.h"
+#include "mozilla/dom/CustomEvent.h"
+#include "mozilla/dom/DocumentFragment.h"
+#include "mozilla/dom/DocumentL10n.h"
+#include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "mozilla/dom/txMozillaXSLTProcessor.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+NS_IMPL_ISUPPORTS(nsXMLPrettyPrinter, nsIDocumentObserver, nsIMutationObserver)
+
+nsXMLPrettyPrinter::nsXMLPrettyPrinter()
+ : mDocument(nullptr), mUnhookPending(false) {}
+
+nsXMLPrettyPrinter::~nsXMLPrettyPrinter() {
+ NS_ASSERTION(!mDocument, "we shouldn't be referencing the document still");
+}
+
+nsresult nsXMLPrettyPrinter::PrettyPrint(Document* aDocument,
+ bool* aDidPrettyPrint) {
+ *aDidPrettyPrint = false;
+
+ // check the pref
+ if (!Preferences::GetBool("layout.xml.prettyprint", true)) {
+ return NS_OK;
+ }
+
+ // Find the root element
+ RefPtr<Element> rootElement = aDocument->GetRootElement();
+ NS_ENSURE_TRUE(rootElement, NS_ERROR_UNEXPECTED);
+
+ // nsXMLContentSink should not ask us to pretty print an XML doc that comes
+ // with a CanAttachShadowDOM() == true root element, but just in case:
+ if (rootElement->CanAttachShadowDOM()) {
+ MOZ_DIAGNOSTIC_ASSERT(false, "We shouldn't be getting this root element");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ // Ok, we should prettyprint. Let's do it!
+ *aDidPrettyPrint = true;
+ nsresult rv = NS_OK;
+
+ // Load the XSLT
+ nsCOMPtr<nsIURI> xslUri;
+ rv = NS_NewURI(getter_AddRefs(xslUri),
+ "chrome://global/content/xml/XMLPrettyPrint.xsl"_ns);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<Document> xslDocument;
+ rv = nsSyncLoadService::LoadDocument(
+ xslUri, nsIContentPolicy::TYPE_XSLT, nsContentUtils::GetSystemPrincipal(),
+ nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, nullptr,
+ aDocument->CookieJarSettings(), true, ReferrerPolicy::_empty,
+ getter_AddRefs(xslDocument));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Transform the document
+ RefPtr<txMozillaXSLTProcessor> transformer = new txMozillaXSLTProcessor();
+ ErrorResult err;
+ transformer->ImportStylesheet(*xslDocument, err);
+ if (NS_WARN_IF(err.Failed())) {
+ return err.StealNSResult();
+ }
+
+ RefPtr<DocumentFragment> resultFragment =
+ transformer->TransformToFragment(*aDocument, *aDocument, err);
+ if (NS_WARN_IF(err.Failed())) {
+ return err.StealNSResult();
+ }
+
+ // Attach an UA Widget Shadow Root on it.
+ rootElement->AttachAndSetUAShadowRoot(Element::NotifyUAWidgetSetup::No);
+ RefPtr<ShadowRoot> shadowRoot = rootElement->GetShadowRoot();
+ MOZ_RELEASE_ASSERT(shadowRoot && shadowRoot->IsUAWidget(),
+ "There should be a UA Shadow Root here.");
+
+ // Append the document fragment to the shadow dom.
+ shadowRoot->AppendChild(*resultFragment, err);
+ if (NS_WARN_IF(err.Failed())) {
+ return err.StealNSResult();
+ }
+
+ // Create a DocumentL10n, as the XML document is not allowed to have one.
+ // Make it sync so that the test for bug 590812 does not require a setTimeout.
+ RefPtr<DocumentL10n> l10n = DocumentL10n::Create(aDocument, true);
+ NS_ENSURE_TRUE(l10n, NS_ERROR_UNEXPECTED);
+ l10n->AddResourceId("dom/XMLPrettyPrint.ftl"_ns);
+
+ // Localize the shadow DOM header
+ Element* l10nRoot = shadowRoot->GetElementById(u"header"_ns);
+ NS_ENSURE_TRUE(l10nRoot, NS_ERROR_UNEXPECTED);
+ l10n->SetRootInfo(l10nRoot);
+ l10n->ConnectRoot(*l10nRoot, true, err);
+ if (NS_WARN_IF(err.Failed())) {
+ return err.StealNSResult();
+ }
+ RefPtr<Promise> promise = l10n->TranslateRoots(err);
+ if (NS_WARN_IF(err.Failed())) {
+ return err.StealNSResult();
+ }
+
+ // Observe the document so we know when to switch to "normal" view
+ aDocument->AddObserver(this);
+ mDocument = aDocument;
+
+ NS_ADDREF_THIS();
+
+ return NS_OK;
+}
+
+void nsXMLPrettyPrinter::MaybeUnhook(nsIContent* aContent) {
+ // If aContent is null, the document-node was modified.
+ // If it is not null but in the shadow tree or the <scrollbar> NACs,
+ // the change was in the generated content, and it should be ignored.
+ bool isGeneratedContent =
+ aContent &&
+ (aContent->IsInNativeAnonymousSubtree() || aContent->IsInShadowTree());
+
+ if (!isGeneratedContent && !mUnhookPending) {
+ // Can't blindly to mUnhookPending after AddScriptRunner,
+ // since AddScriptRunner _could_ in theory run us
+ // synchronously
+ mUnhookPending = true;
+ nsContentUtils::AddScriptRunner(NewRunnableMethod(
+ "nsXMLPrettyPrinter::Unhook", this, &nsXMLPrettyPrinter::Unhook));
+ }
+}
+
+void nsXMLPrettyPrinter::Unhook() {
+ mDocument->RemoveObserver(this);
+ nsCOMPtr<Element> element = mDocument->GetDocumentElement();
+
+ if (element) {
+ // Remove the shadow root
+ element->UnattachShadow();
+ }
+
+ mDocument = nullptr;
+
+ NS_RELEASE_THIS();
+}
+
+void nsXMLPrettyPrinter::AttributeChanged(Element* aElement,
+ int32_t aNameSpaceID,
+ nsAtom* aAttribute, int32_t aModType,
+ const nsAttrValue* aOldValue) {
+ MaybeUnhook(aElement);
+}
+
+void nsXMLPrettyPrinter::ContentAppended(nsIContent* aFirstNewContent) {
+ MaybeUnhook(aFirstNewContent->GetParent());
+}
+
+void nsXMLPrettyPrinter::ContentInserted(nsIContent* aChild) {
+ MaybeUnhook(aChild->GetParent());
+}
+
+void nsXMLPrettyPrinter::ContentRemoved(nsIContent* aChild,
+ nsIContent* aPreviousSibling) {
+ MaybeUnhook(aChild->GetParent());
+}
+
+void nsXMLPrettyPrinter::NodeWillBeDestroyed(nsINode* aNode) {
+ mDocument = nullptr;
+ NS_RELEASE_THIS();
+}
+
+nsresult NS_NewXMLPrettyPrinter(nsXMLPrettyPrinter** aPrinter) {
+ *aPrinter = new nsXMLPrettyPrinter;
+ NS_ADDREF(*aPrinter);
+ return NS_OK;
+}
diff --git a/dom/xml/nsXMLPrettyPrinter.h b/dom/xml/nsXMLPrettyPrinter.h
new file mode 100644
index 0000000000..04835666dd
--- /dev/null
+++ b/dom/xml/nsXMLPrettyPrinter.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsXMLPrettyPrinter_h__
+#define nsXMLPrettyPrinter_h__
+
+#include "nsStubDocumentObserver.h"
+#include "nsCOMPtr.h"
+
+class nsXMLPrettyPrinter : public nsStubDocumentObserver {
+ public:
+ nsXMLPrettyPrinter();
+
+ NS_DECL_ISUPPORTS
+
+ // nsIMutationObserver
+ NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
+ NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
+ NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
+ NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
+ NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
+
+ /**
+ * This will prettyprint the document if the document is loaded in a
+ * displayed window.
+ *
+ * @param aDocument document to prettyprint
+ * @param [out] aDidPrettyPrint if true, and error not returned, actually
+ * went ahead with prettyprinting the document.
+ */
+ nsresult PrettyPrint(mozilla::dom::Document* aDocument,
+ bool* aDidPrettyPrint);
+
+ /**
+ * Unhook the prettyprinter
+ */
+ void Unhook();
+
+ private:
+ virtual ~nsXMLPrettyPrinter();
+
+ /**
+ * Signals for unhooking by setting mUnhookPending if the node changed is
+ * not in the shadow root tree nor in anonymous content.
+ *
+ * @param aContent content that has changed
+ */
+ void MaybeUnhook(nsIContent* aContent);
+
+ mozilla::dom::Document*
+ mDocument; // weak. Set as long as we're observing the document
+ bool mUnhookPending;
+};
+
+nsresult NS_NewXMLPrettyPrinter(nsXMLPrettyPrinter** aPrinter);
+
+#endif // nsXMLPrettyPrinter_h__
diff --git a/dom/xml/resources/XMLPrettyPrint.css b/dom/xml/resources/XMLPrettyPrint.css
new file mode 100644
index 0000000000..845833c46f
--- /dev/null
+++ b/dom/xml/resources/XMLPrettyPrint.css
@@ -0,0 +1,58 @@
+@charset "UTF-8";
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+@import url("resource://content-accessible/viewsource.css");
+
+:host {
+ color-scheme: light dark;
+}
+
+#header {
+ background-color: #ccc;
+ border-bottom: 3px solid black;
+ padding: 0.5em;
+ margin-bottom: 1em;
+}
+
+@media (prefers-color-scheme: dark) {
+ #header {
+ background-color: #333;
+ border-color: #555;
+ }
+}
+
+#tree,
+.expandable-children {
+ margin-inline-start: 1em;
+}
+
+.expandable-body {
+ display: inline-block;
+}
+
+.expandable-body[open] {
+ display: block;
+}
+
+.expandable-opening {
+ list-style: '+' outside;
+}
+
+[open] > .expandable-opening {
+ list-style-type: '−';
+}
+
+.expandable-opening::marker {
+ cursor: pointer;
+ padding-inline-end: 2px;
+ /* Don't want to inherit the styling from pi and comment elements */
+ color: buttontext;
+ font: initial;
+}
+
+.comment {
+ font-family: monospace;
+ white-space: pre;
+}
diff --git a/dom/xml/resources/XMLPrettyPrint.xsl b/dom/xml/resources/XMLPrettyPrint.xsl
new file mode 100644
index 0000000000..b23296cf0d
--- /dev/null
+++ b/dom/xml/resources/XMLPrettyPrint.xsl
@@ -0,0 +1,133 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE overlay>
+
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns="http://www.w3.org/1999/xhtml">
+
+ <xsl:output method="xml"/>
+
+ <xsl:template match="/">
+ <div id="top">
+ <link rel="stylesheet" href="chrome://global/content/xml/XMLPrettyPrint.css"/>
+ <div id="header">
+ <p data-l10n-id="xml-nostylesheet"></p>
+ </div>
+ <main id="tree" class="highlight">
+ <xsl:apply-templates/>
+ </main>
+ </div>
+ </xsl:template>
+
+ <xsl:template match="*">
+ <div>
+ <xsl:text>&lt;</xsl:text>
+ <span class="start-tag"><xsl:value-of select="name(.)"/></span>
+ <xsl:apply-templates select="@*"/>
+ <xsl:text>/&gt;</xsl:text>
+ </div>
+ </xsl:template>
+
+ <xsl:template match="*[node()]">
+ <div>
+ <xsl:text>&lt;</xsl:text>
+ <span class="start-tag"><xsl:value-of select="name(.)"/></span>
+ <xsl:apply-templates select="@*"/>
+ <xsl:text>&gt;</xsl:text>
+
+ <span class="text"><xsl:value-of select="."/></span>
+
+ <xsl:text>&lt;/</xsl:text>
+ <span class="end-tag"><xsl:value-of select="name(.)"/></span>
+ <xsl:text>&gt;</xsl:text>
+ </div>
+ </xsl:template>
+
+ <xsl:template match="*[* or processing-instruction() or comment() or string-length(.) &gt; 50]">
+ <div>
+ <details open="" class="expandable-body">
+ <summary class="expandable-opening">
+ <xsl:text>&lt;</xsl:text>
+ <span class="start-tag"><xsl:value-of select="name(.)"/></span>
+ <xsl:apply-templates select="@*"/>
+ <xsl:text>&gt;</xsl:text>
+ </summary>
+
+ <div class="expandable-children"><xsl:apply-templates/></div>
+
+ </details>
+ <span class="expandable-closing">
+ <xsl:text>&lt;/</xsl:text>
+ <span class="end-tag"><xsl:value-of select="name(.)"/></span>
+ <xsl:text>&gt;</xsl:text>
+ </span>
+ </div>
+ </xsl:template>
+
+ <xsl:template match="@*">
+ <xsl:text> </xsl:text>
+ <span class="attribute-name"><xsl:value-of select="name(.)"/></span>
+ <xsl:text>=</xsl:text>
+ <span class="attribute-value">"<xsl:value-of select="."/>"</span>
+ </xsl:template>
+
+ <xsl:template match="text()">
+ <xsl:if test="normalize-space(.)">
+ <xsl:value-of select="."/>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="processing-instruction()">
+ <div class="pi">
+ <xsl:text>&lt;?</xsl:text>
+ <xsl:value-of select="name(.)"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>?&gt;</xsl:text>
+ </div>
+ </xsl:template>
+
+ <xsl:template match="processing-instruction()[string-length(.) &gt; 50]">
+ <div class="pi">
+ <details open="" class="expandable-body">
+ <summary class="expandable-opening">
+ <xsl:text>&lt;?</xsl:text>
+ <xsl:value-of select="name(.)"/>
+ </summary>
+ <div class="expandable-children"><xsl:value-of select="."/></div>
+ </details>
+ <span class="expandable-closing">
+ <xsl:text>?&gt;</xsl:text>
+ </span>
+ </div>
+ </xsl:template>
+
+ <xsl:template match="comment()">
+ <div class="comment">
+ <xsl:text>&lt;!--</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>--&gt;</xsl:text>
+ </div>
+ </xsl:template>
+
+ <xsl:template match="comment()[string-length(.) &gt; 50]">
+ <div class="comment">
+ <details open="" class="expandable-body">
+ <summary class="expandable-opening">
+ <xsl:text>&lt;!--</xsl:text>
+ </summary>
+ <div class="expandable-children">
+ <xsl:value-of select="."/>
+ </div>
+ </details>
+ <span class="expandable-closing">
+ <xsl:text>--&gt;</xsl:text>
+ </span>
+ </div>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/dom/xml/resources/jar.mn b/dom/xml/resources/jar.mn
new file mode 100644
index 0000000000..14fc365a3e
--- /dev/null
+++ b/dom/xml/resources/jar.mn
@@ -0,0 +1,7 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+toolkit.jar:
+ content/global/xml/XMLPrettyPrint.css (XMLPrettyPrint.css)
+ content/global/xml/XMLPrettyPrint.xsl (XMLPrettyPrint.xsl)
diff --git a/dom/xml/resources/moz.build b/dom/xml/resources/moz.build
new file mode 100644
index 0000000000..d988c0ff9b
--- /dev/null
+++ b/dom/xml/resources/moz.build
@@ -0,0 +1,7 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+JAR_MANIFESTS += ["jar.mn"]
diff --git a/dom/xml/test/file_bug293347.xml b/dom/xml/test/file_bug293347.xml
new file mode 100644
index 0000000000..d041450e2f
--- /dev/null
+++ b/dom/xml/test/file_bug293347.xml
@@ -0,0 +1,2 @@
+<?xml-stylesheet type="text/xsl" href="file_bug293347xslt.xml"?>
+<doc/> \ No newline at end of file
diff --git a/dom/xml/test/file_bug293347xslt.xml b/dom/xml/test/file_bug293347xslt.xml
new file mode 100644
index 0000000000..44df7749e0
--- /dev/null
+++ b/dom/xml/test/file_bug293347xslt.xml
@@ -0,0 +1,19 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:template match="/doc">
+ <html>
+ <body>
+ <div></div>
+ <div>
+ <script>
+ didThrow = false;
+ try {
+ document.write("shrimp");
+ } catch (e) {
+ didThrow = true;
+ }
+ </script>
+ </div>
+ </body>
+ </html>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/dom/xml/test/file_bug343870.xml b/dom/xml/test/file_bug343870.xml
new file mode 100644
index 0000000000..cf9c60544c
--- /dev/null
+++ b/dom/xml/test/file_bug343870.xml
@@ -0,0 +1,6 @@
+<?xml version='1.0' encoding='utf-8'?>
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<p id='lf'>
+</p><p id='cr'>
+</p><p id='crlf'>
+</p><p id='escapedcr'>&#13;</p></html>
diff --git a/dom/xml/test/file_bug691215.xml b/dom/xml/test/file_bug691215.xml
new file mode 100644
index 0000000000..37ae932348
--- /dev/null
+++ b/dom/xml/test/file_bug691215.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<root/>
diff --git a/dom/xml/test/mochitest.ini b/dom/xml/test/mochitest.ini
new file mode 100644
index 0000000000..707122eb7b
--- /dev/null
+++ b/dom/xml/test/mochitest.ini
@@ -0,0 +1,14 @@
+[DEFAULT]
+support-files =
+ file_bug293347.xml
+ file_bug293347xslt.xml
+ file_bug343870.xml
+ file_bug691215.xml
+
+[test_bug232004.xhtml]
+[test_bug293347.html]
+[test_bug343870.xhtml]
+[test_bug355213.xhtml]
+[test_bug691215.html]
+skip-if =
+ http3
diff --git a/dom/xml/test/old/books/bethlehem.gif b/dom/xml/test/old/books/bethlehem.gif
new file mode 100644
index 0000000000..db41f52fb4
--- /dev/null
+++ b/dom/xml/test/old/books/bethlehem.gif
Binary files differ
diff --git a/dom/xml/test/old/books/bill.gif b/dom/xml/test/old/books/bill.gif
new file mode 100644
index 0000000000..4b00f890cb
--- /dev/null
+++ b/dom/xml/test/old/books/bill.gif
Binary files differ
diff --git a/dom/xml/test/old/books/books.js b/dom/xml/test/old/books/books.js
new file mode 100644
index 0000000000..cf233a7b93
--- /dev/null
+++ b/dom/xml/test/old/books/books.js
@@ -0,0 +1,90 @@
+// An inefficient, but effective bubble sort
+function sort(collection, key) {
+ var i, j;
+ var count = collection.length;
+ var parent, child;
+
+ for (i = count - 1; i >= 0; i--) {
+ for (j = 1; j <= i; j++) {
+ if (collection[j - 1][key] > collection[j][key]) {
+ // Move the item both in the local array and
+ // in the tree
+ child = collection[j];
+ parent = child.parentNode;
+
+ collection[j] = collection[j - 1];
+ collection[j - 1] = child;
+
+ parent.removeChild(child);
+ parent.insertBefore(child, collection[j]);
+ }
+ }
+ }
+}
+
+// Set user properties on the nodes in the collection
+// based on information found in its children. For example,
+// make a property "Author" based on the content of the
+// "Author" element found in the childNode list of the node.
+// This makes later sorting more efficient
+function collectInfo(nodes, propNames) {
+ var i, j, k;
+ var ncount = nodes.length;
+ var pcount = propNames.length;
+
+ for (i = 0; i < ncount; i++) {
+ var node = nodes[i];
+ var childNodes = node.childNodes;
+ var ccount = childNodes.length;
+
+ for (j = 0; j < ccount; j++) {
+ var child = childNodes[j];
+
+ if (child.nodeType == Node.ELEMENT_NODE) {
+ var tagName = child.tagName;
+
+ for (k = 0; k < pcount; k++) {
+ var prop = propNames[k];
+ if (prop == tagName) {
+ node[prop] = child.firstChild.data;
+ }
+ }
+ }
+ }
+ }
+}
+
+var enabled = true;
+function toggleStyleSheet() {
+ if (enabled) {
+ document.styleSheets[2].disabled = true;
+ } else {
+ document.styleSheets[2].disabled = false;
+ }
+
+ enabled = !enabled;
+}
+
+// XXX This is a workaround for a bug where
+// changing the disabled state of a stylesheet can't
+// be done in an event handler. For now, we do it
+// in a zero-delay timeout.
+function initiateToggle() {
+ setTimeout(toggleStyleSheet, 0);
+}
+
+var sortableProps = new Array("Author", "Title", "ISBN");
+var books = new Array();
+
+// We uppercase the tagName as a workaround for a bug
+// that loses the original case of the tag.
+var bookset = document.getElementsByTagName("Book");
+
+// We need to create a "non-live" array to operate on. Since
+// we'll be moving things around in this array, we can't use
+// the read-only, live one returned by getElementsByTagName.
+for (var i = 0; i < bookset.length; i++) {
+ books[i] = bookset[i];
+}
+
+collectInfo(books, sortableProps);
diff --git a/dom/xml/test/old/books/books.xml b/dom/xml/test/old/books/books.xml
new file mode 100644
index 0000000000..2067487d8d
--- /dev/null
+++ b/dom/xml/test/old/books/books.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="common.css" type="text/css"?>
+<?xml-stylesheet href="classic.css" type="text/css"?>
+<?xml-stylesheet href="list.css" type="text/css"?>
+
+<!DOCTYPE SearchResult>
+
+<SearchResult xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<Header>
+ <Toolbar>
+ <html:form>
+ <Label>Sort by:</Label>
+ <html:input type="button" id="Author" onclick="sort(books,this.id)" value="Author"/>
+ <html:input type="button" id="Title" onclick="sort(books,this.id)" value="Title"/>
+ <html:input type="button" id="ISBN" onclick="sort(books,this.id)" value="ISBN #"/>
+ <html:input type="button" id="toggle" value="Toggle Style" onclick="initiateToggle(); return false;"/>
+ </html:form>
+ </Toolbar>
+
+ <SearchTitle>Amazon.com Search Results for: the keywords include "Road"</SearchTitle>
+</Header>
+
+<BookSet>
+
+ <Book>
+ <BookCover><html:img src="kerouac.gif" width="100" height="140"/></BookCover>
+ <Title xlink:type="simple" xlink:show="replace" xlink:href="http://www.amazon.com/exec/obidos/ASIN/0140042598/002-5969498-2733628">On the Road</Title>
+ <Author>Kerouac, Jack</Author>
+ <ISBN>0140042598</ISBN>
+ <Synopsis>
+On The Road, the most famous of Jack Kerouac's works, is not only the soul of the Beat movement and literature, but one of the most important novels of the century. Like nearly all of Kerouac's writing, On The Road is thinly fictionalized autobiography, filled with a cast made of Kerouac's real life friends, lovers, and fellow travelers. Narrated by Sal Paradise, one of Kerouac's alter-egos, On the Road is a cross-country bohemian odyssey that not only influenced writing in the years since its 1957 publication but penetrated into the deepest levels of American thought and culture.
+ </Synopsis>
+ <ListPrice>$12.95</ListPrice>
+ <Price>$10.36</Price>
+ </Book>
+
+ <Book>
+ <BookCover><html:img src="bill.gif" width="100" height="140" /></BookCover>
+ <Title xlink:type="simple" xlink:show="replace" xlink:href="http://www.amazon.com/exec/obidos/ASIN/0140260404/002-5969498-2733628">The Road Ahead</Title>
+ <Author>Gates, Bill</Author>
+ <ISBN>666666666</ISBN>
+ <Synopsis>
+In a study, the founder of Microsoft presents his vision for the future in which he sees the digital technologies of the coming years changing the way we buy, work, learn, and communicate. But he doesn't mention XML!
+ </Synopsis>
+ <ListPrice>$15.95</ListPrice>
+ <Price>$12.76</Price>
+ </Book>
+
+ <Book>
+ <BookCover><html:img src="welville.gif" width="100" height="140" /></BookCover>
+ <Title xlink:type="simple" xlink:show="replace" xlink:href="http://www.amazon.com/exec/obidos/ASIN/0140167188/002-5969498-2733628">The Road to Wellville</Title>
+ <Author>Boyle, T. Coraghessan</Author>
+ <ISBN>0140167188</ISBN>
+ <Synopsis>
+A snobbish wife and her henpecked husband travel to Dr. Kellogg's spa in turn-of-the-century Battle Creek, where the youth-crazed affluent succumb to quackery. By the author of East is East.
+ </Synopsis>
+ <ListPrice>$12.95</ListPrice>
+ <Price>$10.36</Price>
+ </Book>
+
+ <Book>
+ <BookCover><html:img src="road.gif" width="100" height="140" /></BookCover>
+ <Title xlink:type="simple" xlink:show="replace" xlink:href="http://www.amazon.com/exec/obidos/ASIN/1562512625/002-5969498-2733628">AAA Road Atlas 1999</Title>
+ <Author>A. A. A.</Author>
+ <ISBN>1562512625</ISBN>
+ <Synopsis>
+The definitive road atlas to the United States, Canada and Mexico.
+ </Synopsis>
+ <ListPrice>$9.95</ListPrice>
+ <Price>$9.95</Price>
+ </Book>
+
+ <Book>
+ <BookCover><html:img src="bethlehem.gif" width="100" height="140" /></BookCover>
+ <Title xlink:type="simple" xlink:show="replace" xlink:href="http://www.amazon.com/exec/obidos/ASIN/0449219143/002-5969498-2733628">Bethlehem Road</Title>
+ <Author>Perry, Anne</Author>
+ <ISBN>0449219143</ISBN>
+ <Synopsis>
+He might be elegant, but there's no mistaking it--the gentleman tied to the lamppost on Westminster Bridge is definitely dead. Before Inspector Thomas Pitt can even speculate on why anyone should want to kill the eminent M.P., Sir Lockwood, a colleague of his, meets the same fate at the same spot. The public is outraged, and clever Charlotte Pitt, Thomas's well-born wife, helps her hard-pressed husband by scouting society's drawing rooms for clues to these appalling crimes. Meanwhile, another victim is being stalked....
+ </Synopsis>
+ <ListPrice>$6.99</ListPrice>
+ <Price>$5.59</Price>
+ </Book>
+
+ <Book>
+ <BookCover><html:img src="charing.gif" width="100" height="140" /></BookCover>
+ <Title xlink:type="simple" xlink:show="replace" xlink:href="http://www.amazon.com/exec/obidos/ASIN/0140143505/002-5969498-2733628">84 Charing Cross Road</Title>
+ <Author>Hanff, Helene</Author>
+ <ISBN>0140143505</ISBN>
+ <Synopsis>
+84, Charing Cross Road is a charming record of bibliophilia, cultural difference, and imaginative sympathy. For 20 years, an outspoken New York writer and a rather more restrained London bookseller carried on an increasingly touching correspondence...
+ </Synopsis>
+ <ListPrice>$9.95</ListPrice>
+ <Price>$7.96</Price>
+ </Book>
+
+</BookSet>
+
+<html:script src="books.js" />
+
+</SearchResult>
diff --git a/dom/xml/test/old/books/charing.gif b/dom/xml/test/old/books/charing.gif
new file mode 100644
index 0000000000..9a63fb0b27
--- /dev/null
+++ b/dom/xml/test/old/books/charing.gif
Binary files differ
diff --git a/dom/xml/test/old/books/classic.css b/dom/xml/test/old/books/classic.css
new file mode 100644
index 0000000000..1ebc92f6e8
--- /dev/null
+++ b/dom/xml/test/old/books/classic.css
@@ -0,0 +1,78 @@
+
+
+BookSet {
+ display: block;
+}
+
+Book {
+ float: left;
+ display: block;
+ width: 300px;
+ background-color: #f1f1f1;
+ border: 1px solid #cccccc;
+ margin-right: 8px;
+ margin-top: 8px;
+}
+
+BookCover {
+ display: inline;
+ float: left;
+ margin-right: 10px;
+ padding: 5px;
+ width: 100px;
+ height: 140px;
+}
+
+Title {
+ display: block;
+ font-weight: bold;
+ color: blue;
+ text-decoration: underline;
+ cursor: pointer;
+}
+
+Author {
+ display: block;
+ font-style: italic;
+}
+
+Synopsis {
+ display: block;
+ overflow: scroll;
+ height: 100px;
+ width: 155px;
+ padding: 3px;
+ background-color: #ddddff;
+}
+
+
+ListPrice {
+ display: block;
+ text-align: right;
+ padding-right: 15px;
+ text-decoration: line-through;
+}
+
+
+Price {
+ display: block;
+ color: rgb(20,100,0);
+ text-align:right;
+ padding-right: 15px;
+ font-weight: bold;
+}
+
+
+Price:before {
+ content: "Our Price: ";
+}
+
+ISBN {
+ display: block;
+ font-family: monospace;
+ font-size: 8pt;
+}
+
+
+
+
diff --git a/dom/xml/test/old/books/common.css b/dom/xml/test/old/books/common.css
new file mode 100644
index 0000000000..d63f09585d
--- /dev/null
+++ b/dom/xml/test/old/books/common.css
@@ -0,0 +1,43 @@
+SearchResult {
+ display: block;
+ margin-top: 8px;
+ margin-left: 8px;
+}
+
+Header {
+ width: 612px;
+ display: block;
+}
+
+SearchTitle {
+ display: block;
+ width: 280px;
+ border-bottom: thin solid black;
+ padding-bottom: 6px;
+ margin-bottom: 12px;
+}
+
+SearchTitle:first-line {
+ font-family: Verdana, Sans-Serif;
+ color: #cc6600;
+ font-size: 14pt;
+}
+
+Toolbar {
+ font-family: Verdana, Sans-Serif;
+ float: right;
+ font-size: 7pt;
+ display: block;
+ border: ridge #ddddff 4px;
+ width: 220px;
+ margin-right: 0px;
+ text-align: center;
+}
+
+Label {
+ font-weight: bold;
+}
+
+input {
+ margin-top: 2px;
+} \ No newline at end of file
diff --git a/dom/xml/test/old/books/kerouac.gif b/dom/xml/test/old/books/kerouac.gif
new file mode 100644
index 0000000000..df2b371d07
--- /dev/null
+++ b/dom/xml/test/old/books/kerouac.gif
Binary files differ
diff --git a/dom/xml/test/old/books/list.css b/dom/xml/test/old/books/list.css
new file mode 100644
index 0000000000..3b5d408915
--- /dev/null
+++ b/dom/xml/test/old/books/list.css
@@ -0,0 +1,61 @@
+
+BookSet {
+ display: block;
+}
+
+Book {
+ display: list-item;
+ float: none;
+ border: none;
+ background: inherit;
+}
+
+BookCover {
+ display: none;
+}
+
+Title {
+ display: block;
+ font-weight: bold;
+ color: blue;
+ text-decoration: underline;
+ cursor: pointer;
+}
+
+Author {
+ display: block;
+ font-style: italic;
+}
+
+Synopsis {
+ display: none;
+}
+
+
+ListPrice {
+ display: none;
+ text-align: right;
+ padding-right: 15px;
+ text-decoration: line-through;
+}
+
+
+Price {
+ display: block;
+ color: rgb(20,100,0);
+ font-weight: bold;
+ text-align:left;
+}
+
+
+Price:before {
+ content: "Our Price: ";
+}
+
+ISBN {
+ display: block;
+ font-family: monospace;
+ font-size: 8pt;
+}
+
+
diff --git a/dom/xml/test/old/books/road.gif b/dom/xml/test/old/books/road.gif
new file mode 100644
index 0000000000..5ba7920c7e
--- /dev/null
+++ b/dom/xml/test/old/books/road.gif
Binary files differ
diff --git a/dom/xml/test/old/books/welville.gif b/dom/xml/test/old/books/welville.gif
new file mode 100644
index 0000000000..7ff24a99ec
--- /dev/null
+++ b/dom/xml/test/old/books/welville.gif
Binary files differ
diff --git a/dom/xml/test/old/docbook.css b/dom/xml/test/old/docbook.css
new file mode 100644
index 0000000000..562c8d2133
--- /dev/null
+++ b/dom/xml/test/old/docbook.css
@@ -0,0 +1,621 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+Book {
+ display: block;
+ padding-left: 8px;
+ padding-top: 8px;
+ font-family: Courier;
+ font-size: 10pt;
+}
+
+Abbrev {
+ display: block;
+}
+
+Affiliation {
+ font-style: italic;
+}
+
+Appendix Title {
+ font-weight: bold;
+ font-family: Arial;
+ font-size: 24pt;
+ margin-bottom: 10pt;
+ display: block;
+}
+
+Para Author {
+ display: inline;
+}
+
+Author {
+ display: block;
+}
+
+AuthorGroup {
+ font-size: 12pt;
+ margin-top: 25pt;
+ display: block;
+ font-weight: bold;
+}
+
+BiblioDiv Title {
+ font-style: italic;
+}
+
+Blockquote {
+ display: block;
+ margin-top: 3pt;
+ margin-left: 30pt;
+}
+
+Book Title {
+ font-weight: bold;
+ font-family: Arial;
+ font-size: 18pt;
+ margin-bottom: 10pt;
+ display: block;
+}
+
+BookInfo {
+ display: block;
+ margin-bottom: 30pt;
+}
+
+BridgeHead {
+ display: block;
+ font-size: 16pt;
+ font-weight: bold;
+ color: teal;
+}
+
+Caution {
+ font-weight: bold;
+ color: red;
+}
+
+Caution:before {
+ content: "Caution:";
+}
+
+Chapter {
+ display: block;
+ margin-bottom: 25pt;
+}
+
+Chapter Title {
+ font-weight: bold;
+ font-family: Arial;
+ font-size: 20pt;
+ margin-bottom: 10pt;
+ display: block;
+}
+
+CiteTitle {
+ font-style: italic;
+}
+
+CmdSynopsis {
+ display: block;
+}
+
+CO {
+ display: block;
+}
+
+Command {
+ font-style: italic;
+}
+
+Comment {
+ display: block;
+}
+
+ComputerOutput {
+ font-family: monospace;
+}
+
+Copyright {
+ display: block;
+}
+
+Para CorpAuthor {
+ display: inline;
+}
+
+CorpAuthor {
+ display: block;
+}
+
+Email {
+ font-style: italic;
+}
+
+Editor {
+ display: block;
+}
+
+Emphasis {
+ font-style: italic;
+}
+
+ErrorType {
+ font-family: monospace;
+}
+
+Example {
+ display: block;
+ margin-top: 10pt;
+ margin-bottom: 10pt;
+}
+
+Example Title {
+ display: block;
+ font-weight: bold;
+ font-size: 14pt;
+}
+
+Figure Title {
+ font-family: Arial;
+ font-size: 10pt;
+ font-style: italic;
+ font-weight: bold;
+ display: block;
+}
+
+Filename {
+ font-style: italic;
+}
+
+Figure {
+ display: block;
+ margin-top: 10pt;
+}
+
+FirstTerm {
+ font-style: italic;
+}
+
+ForeignPhrase {
+ font-style: italic;
+}
+
+FormalPara {
+ display: block;
+}
+
+FormalPara Title {
+ display: block;
+ font-weight: bold;
+}
+
+FuncSynopsis {
+ display: block;
+}
+
+FuncSynopsisInfo {
+ display: block;
+ white-space: pre;
+}
+
+Function {
+ font-family: monospace;
+ white-space: pre;
+}
+
+Glossary {
+ display: block;
+}
+
+GlossDef {
+ display: block;
+ margin-left: 15pt;
+}
+
+GlossList {
+ display: block;
+}
+
+GlossSee {
+ display: block;
+ margin-left: 15pt;
+}
+
+GlossTerm {
+ display: block;
+ font-weight: bold;
+}
+
+InformalTable {
+ display: block;
+ margin-top: 10pt;
+ margin-bottom: 10pt;
+}
+
+Interface {
+ font-family: Arial;
+}
+
+ISBN {
+ display: block;
+ font-size: 10pt;
+}
+
+ItemizedList {
+ display: block;
+ margin-top: 5pt;
+ margin-left: 20pt;
+}
+
+LineAnnotation {
+ font-style: italic;
+}
+
+Link {
+ color: blue;
+ text-decoration: underline;
+}
+
+ListItem {
+ margin-left: 25pt;
+ display: list-item;
+}
+
+Literal {
+ font-family: monospace;
+}
+
+LiteralLayout {
+ white-space: pre;
+ display: block;
+}
+
+Member {
+ display: block;
+ margin-left: 15pt;
+}
+
+OLink {
+ display: block;
+ font-size: 12pt;
+}
+
+Option {
+ font-family: monospace;
+}
+
+OrderedList {
+ margin-top: 5pt;
+ margin-left: 20pt;
+ margin-bottom: 10pt;
+ display: block;
+ list-style-type: decimal;
+}
+
+OrderedList Para {
+ display: block;
+ margin-top: 15pt;
+}
+
+Para OtherCredit {
+ display: inline;
+}
+
+OtherCredit {
+ display: block;
+}
+
+Para {
+ display: block;
+ margin-top: 8pt;
+}
+
+Para LiteralLayout {
+ display: block;
+ margin-top: 4pt;
+ margin-left: 10pt;
+ white-space: pre;
+}
+
+Para Screen {
+ margin-top: 7pt;
+ margin-left: 10pt;
+ margin-bottom: 7pt;
+ display: block;
+}
+
+Parameter {
+ font-family: monospace;
+}
+
+Part Title {
+ font-size: 24pt;
+ display: block;
+ font-weight: bold;
+}
+
+Preface {
+ display: block;
+ margin-top: 10pt;
+}
+
+Procedure {
+ display: block;
+}
+
+ProgramListing {
+ display: block;
+ white-space: pre;
+ font-family: monospace;
+}
+
+ProgramListingCO {
+ display: block;
+ white-space: pre;
+ font-family: monospace;
+}
+
+PublisherName {
+ font-family: Times, New, Roman;
+ font-size: 20pt;
+ margin-top: 15pt;
+ margin-bottom: 15pt;
+ display: block;
+}
+
+RefEntry {
+ display: block;
+}
+
+RefEntryTitle {
+ display: block;
+ font-size: 20pt;
+ font-weight: bold;
+}
+
+RefName {
+ font-weight: bold;
+}
+
+RefNameDiv {
+ display: block;
+}
+
+RefSect1 {
+ display: block;
+ margin-top: 10pt;
+}
+
+RefSect1 Title {
+ font-size: 14pt;
+}
+
+RefSect1Info {
+ display: block;
+ font-size: small;
+}
+
+RefSect2 {
+ display: block;
+ margin-top: 10pt;
+}
+
+RefSect2 Title {
+ font-size: 14pt;
+}
+
+RefSect2Info {
+ display: block;
+ font-size: small;
+}
+
+RefSect3 {
+ display: block;
+ margin-top: 10pt;
+}
+
+RefSect3 Title {
+ font-size: 14pt;
+}
+
+RefSect3Info {
+ display: block;
+ font-size: small;
+}
+
+RefSynopsisDiv {
+ display: block;
+ margin-top: 15pt;
+}
+
+RefSynopsisDiv Title {
+ display: block;
+ font-size: 18pt;
+}
+
+Replaceable {
+ font-family: Arial;
+ font-style: italic;
+}
+
+Screen {
+ display: block;
+ margin-left: 20pt;
+ margin-bottom: 10pt;
+ white-space: pre;
+}
+
+ScreenCO {
+ white-space: pre;
+}
+
+ScreenShot {
+ white-space: pre;
+}
+
+Sect1 {
+ display: block;
+ margin-top: 16pt;
+}
+
+Sect1 Title {
+ font-family: Arial;
+ font-size: 20pt;
+ font-weight: bold;
+ display: block;
+}
+
+Sect2 {
+ display: block;
+ margin-top: 15pt;
+}
+
+Sect2 Title {
+ font-family: Arial;
+ font-size: 14pt;
+ font-weight: bold;
+ display: block;
+}
+
+Sect3 {
+ display: block;
+ margin-top: 15pt;
+}
+
+Sect3 Title {
+ font-family: Arial;
+ font-size: 14pt;
+ font-weight: bold;
+ display: block;
+}
+
+SegListItem {
+ display: block;
+}
+
+SegmentedList {
+ display: block;
+}
+
+SegmentedList Title {
+ display: block;
+ font-weight: bold;
+}
+
+Sidebar {
+ display: block;
+ margin-top: 15pt;
+ margin-left: 30pt;
+ font-family: Arial;
+ font-size: 9pt;
+}
+
+Step {
+ display: block;
+}
+
+Step Title {
+ display: block;
+ font-style: italic;
+}
+
+Subscript {
+ font-size: 5pt;
+ vertical-align: sub;
+}
+
+Subtitle {
+ font-family: Arial;
+ font-size: 20pt;
+ font-weight: bold;
+ display: block;
+ text-align: center;
+}
+
+Superscript {
+ font-size: 5pt;
+ vertical-align: super;
+}
+
+Synopsis {
+ display: block;
+ white-space: pre;
+}
+
+SystemItem {
+ font-family: monospace;
+}
+
+Table {
+ display: block;
+ margin-top: 10pt;
+}
+
+Table Title {
+ font-family: Arial;
+ font-size: 10pt;
+ font-style: italic;
+ font-weight: bold;
+}
+
+Term {
+ font-weight: bold;
+}
+
+Title {
+ font-family: Arial;
+ font-size: 20pt;
+ font-weight: bold;
+ display: block;
+ text-align: center;
+}
+
+TitleAbbrev {
+ font-family: Arial;
+ font-size: 14pt;
+ font-weight: bold;
+ display: block;
+}
+
+ULink {
+ color: blue;
+ text-decoration: underline;
+ cursor: pointer;
+}
+
+UserInput {
+ font-family: monospace;
+ font-weight: bold;
+}
+
+VariableList Title {
+ font-weight: bold;
+ display: block;
+}
+
+VarListEntry {
+ display: block;
+ margin-top: 10pt;
+}
+
+VarListEntry Term {
+ display: block;
+ font-style: italic;
+}
+
+Warning {
+ font-weight: bold;
+ color: fuchsia;
+}
+
+Warning:before {
+ content: "Warning:";
+}
+
+
+Year {
+ font-family: serif;
+ font-weight: bold;
+}
diff --git a/dom/xml/test/old/docbooktest.xml b/dom/xml/test/old/docbooktest.xml
new file mode 100644
index 0000000000..d47c3cb12e
--- /dev/null
+++ b/dom/xml/test/old/docbooktest.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="docbook.css" type="text/css"?>
+<!DOCTYPE Book SYSTEM "docbook.dtd">
+<Book xmlns:xlink="http://www.w3.org/1999/xlink">
+<Title>SoftQuad
+Inc.</Title>
+<p xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://www.w3.org/1999/xhtml">
+<h:img src="flamer.gif"/>
+<img src="flamer.gif"/>
+<button><b>some text</b></button>
+</p>
+<BookInfo> <BookBiblio> <Title>Demo Product Documentation</Title>
+<AuthorGroup><CorpAuthor>SoftQuad Inc.</CorpAuthor></AuthorGroup>
+</BookBiblio> </BookInfo> <Preface> <Title><Anchor
+Id="SDK3"/>Element Overview</Title>
+<BridgeHead>Introduction to Elements</BridgeHead>
+<Para>By far the vast majority of objects (apart from text) that authors
+encounter when traversing a document are Element nodes. </Para> </Preface>
+<Part> <Title><Anchor Id="SDK273"/>Element Interfaces</Title>
+<Chapter Label="1"> <Title><Anchor Id="SDK274"/>Elements and
+Attributes</Title>
+<Sect1> <Title><Anchor Id="SDK279"/>Introduction to Attributes
+</Title>
+<Para>Elements may have attributes associated with them; since the Element
+interface inherits from Node, the generic Node interface method
+<Function>getAttributes</Function> may be used to retrieve the set of all
+attributes for an element. </Para>
+<Para>There are methods on the Element interface to retrieve either an Attr
+object by name or an attribute value by name. In XML, where an attribute value
+may contain entity references, an Attr object should be retrieved to examine
+the possibly fairly complex sub-tree representing the attribute value. On the
+other hand, in HTML, where all attributes have simple string values, methods to
+directly access an attribute value can safely be used as a convenience. </Para>
+
+<Para>Before you can access an Attribute, you must first gain access to the
+associated Element.</Para> </Sect1>
+<Sect1> <Title><Anchor Id="SDK378"/>Setting the Attribute
+Values</Title>
+<Para>Attr objects inherit the Node interface, but since they are not actually
+child nodes of the element they describe, the DOM does not consider them part
+of the document tree. Thus, the Node attributes parentNode, previousSibling,
+and nextSibling have a null value for Attr objects. The DOM takes the view that
+attributes are properties of elements rather than having a separate identity
+from the elements they are associated with; this should make it more efficient
+to implement such features as default attributes associated with all elements
+of a given type. Furthermore, Attr nodes may not be immediate children of a
+DocumentFragment. However, they can be associated with Element nodes contained
+within a DocumentFragment. In short, users and implementors of the DOM need to
+be aware that Attr nodes have some things in common with other objects
+inheriting the Node interface, but they also are quite distinct. </Para>
+<Para>The attribute's effective value is determined as follows:</Para>
+<ItemizedList Mark="Bullet"> <ListItem>
+<Para>If this attribute has been explicitly assigned any value, that value is
+the attribute's effective value</Para></ListItem> <ListItem>
+<Para>Otherwise, if there is a declaration for this attribute, and that
+declaration includes a default value, then that default value is the
+attribute's effective value</Para></ListItem> <ListItem>
+<Para>Otherwise, the attribute does not exist on this element in the structure
+model until it has been explicitly added.</Para></ListItem> </ItemizedList>
+<Para>In XML, where the value of an attribute can contain entity references,
+the child nodes of the Attr node provide a representation in which entity
+references are not expanded. These child nodes may be either Text or
+EntityReference nodes. Because the attribute type may be unknown, there are no
+tokenized attribute values. </Para>
+<Para>The following topics describe DOM attributes: </Para>
+<ItemizedList Mark="Bullet"> <ListItem>
+<Para>
+<ULink xlink:type="simple" xlink:show="replace"
+ xlink:href="http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-637646024">Interface
+Attr</ULink> </Para></ListItem> <ListItem>
+<Para>
+<ULink xlink:type="simple" xlink:show="new"
+ xlink:href="http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-745549614">
+Interface Element</ULink> </Para></ListItem> </ItemizedList> </Sect1></Chapter>
+
+<Chapter Label="26" Role="funcref"> <Title><Anchor
+Id="SDK48"/>DOM Level 1 Core: Element Functions</Title>
+<RefEntry> <RefMeta><RefEntryTitle> <Anchor Id="setAttribute"/>setAttribute
+</RefEntryTitle></RefMeta> <RefNameDiv> <RefName>setAttribute</RefName>
+<RefPurpose>Sets the Attributes on the associated Element object</RefPurpose>
+<RefClass>Fundamental</RefClass> </RefNameDiv> <RefSynopsisDiv> <Title>
+<Anchor Id="SDK85"/>Syntax</Title>
+<RefSect2> <Title>OMG IDL</Title>
+<Synopsis><Type>void</Type> <Function>setAttribute</Function> (in
+<Type>DOMString</Type> <Parameter>name</Parameter>, in <Type>DOMString</Type>
+<Parameter>value</Parameter>) raises (<ErrorType>DOMException</ErrorType>);
+</Synopsis></RefSect2><RefSect2> <Title><Anchor Id="SDK86"/>Java</Title>
+<Synopsis><Type>public void</Type> <Function>setAttribute</Function> (
+<Type>String</Type> <Parameter>name</Parameter>, <Type>String</Type>
+<Parameter>value</Parameter>) throws (<ErrorType>DOMException</ErrorType>);
+</Synopsis> </RefSect2><RefSect2> <Title><Anchor Id="SDK87"/>ECMA Script
+</Title>
+<Synopsis> <Function>setAttribute</Function> (<Parameter>name, value
+</Parameter>)</Synopsis> </RefSect2></RefSynopsisDiv><RefSect1> <Title>
+<Anchor Id="SDK88"/>Parameters</Title>
+<VariableList> <VarListEntry><Term> <Parameter>name</Parameter></Term>
+<ListItem>
+<Para>(IN) The name of the attribute to create or alter.</Para> </ListItem>
+</VarListEntry><VarListEntry><Term> <Parameter>value</Parameter></Term>
+<ListItem>
+<Para>(IN) Value to set in string form</Para> </ListItem></VarListEntry>
+</VariableList></RefSect1><RefSect1> <Title><Anchor Id="SDK89"/>Exceptions
+</Title>
+<Para>These are the applicable exceptions. </Para> <InformalTable> <TGroup cols="2">
+<colspec colname="1" colnum="1" colwidth="0.630in"/>
+<colspec colname="2" colnum="2" colwidth="5.203in"/> <tbody>
+<row> <entry colname="1">
+<Para>INVALID_CHARACTER_ERR</Para></entry> <entry colname="2">
+<Para>Raised if the specified name contains an invalid character.</Para>
+</entry></row> <row> <entry colname="1">
+<Para> NO_MODIFICATION_ALLOWED_ERR</Para></entry> <entry colname="2">
+<Para>Raised if this node is readonly.</Para></entry> </row>
+</tbody>
+</TGroup></InformalTable></RefSect1><RefSect1> <Title><Anchor
+Id="SDK90"/>Remarks</Title>
+<Para> <Function>setAttribute</Function> adds a new attribute. If an attribute
+with that name is already present in the element, its value is changed to be
+that of the value parameter. This value is a simple string, it is not parsed as
+it is being set. So any markup (such as syntax to be recognized as an entity
+reference) is treated as literal text, and needs to be appropriately escaped by
+the implementation when it is written out.</Para>
+<Para> In order to assign an attribute value that contains entity references,
+the user must create an Attr node plus any Text and EntityReference nodes,
+build the appropriate subtree, and use <Function>setAttributeNode</Function> to
+assign it as the value of an attribute. </Para> </RefSect1></RefEntry>
+</Chapter></Part></Book>
diff --git a/dom/xml/test/old/flamer.gif b/dom/xml/test/old/flamer.gif
new file mode 100644
index 0000000000..5a05df583f
--- /dev/null
+++ b/dom/xml/test/old/flamer.gif
Binary files differ
diff --git a/dom/xml/test/old/script.xml b/dom/xml/test/old/script.xml
new file mode 100644
index 0000000000..f21d30d973
--- /dev/null
+++ b/dom/xml/test/old/script.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="docbook.css" type="text/css"?>
+<!DOCTYPE Book System "file:///E|/Program%20Files/SoftQuad/XMetaL/Rules/docbook.dtd">
+<Book xmlns:html="http://www.w3.org/1999/xhtml">
+ <Title>The Book</Title>
+ <Chapter>
+ <Title>Chapter 1.</Title>
+ <Para>Yada yada <html:img src="mzcolor.gif"/> yada.</Para>
+ </Chapter>
+ <html:script>
+<![CDATA[
+function list(node)
+{
+ var type = node.nodeType;
+ if (type == Node.ELEMENT_NODE) {
+
+ // open tag
+ dump("\<" + node.tagName);
+
+ // dump the attributes if any
+ attributes = node.attributes;
+ if (null != attributes) {
+ var countAttrs = attributes.length;
+ var index = 0;
+ while(index < countAttrs) {
+ att = attributes[index];
+ if (null != att) {
+ dump(" " + att.name + "=" + att.value);
+ }
+ index++;
+ }
+ }
+
+ // recursively dump the children
+ if (node.hasChildNodes()) {
+ // close tag
+ dump(">");
+
+ // get the children
+ var children = node.childNodes;
+ var length = children.length;
+ var count = 0;
+ while(count < length) {
+ child = children[count];
+ list(child);
+ count++;
+ }
+ dump("</" + node.tagName + ">");
+ }
+ else {
+ // close tag
+ dump("/>");
+ }
+
+
+ }
+ // if it's a piece of text just dump the text
+ else if (type == Node.TEXT_NODE) {
+ dump(node.data);
+ }
+}
+
+list(document.documentElement);
+dump("\n");
+]]>
+ </html:script>
+</Book>
diff --git a/dom/xml/test/old/simple.xml b/dom/xml/test/old/simple.xml
new file mode 100644
index 0000000000..c94708c665
--- /dev/null
+++ b/dom/xml/test/old/simple.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="docbook.css" type="text/css"?>
+<!DOCTYPE Book SYSTEM "file:///E|/Program%20Files/SoftQuad/XMetaL/Rules/docbook.dtd">
+<Book xmlns:html="http://www.w3.org/1999/xhtml">
+ <Title>The Book</Title>
+ <Chapter>
+ <Title>Chapter 1.</Title>
+ <Para>Yada yada <html:img src="mzcolor.gif"/> yada.</Para>
+ </Chapter>
+</Book>
diff --git a/dom/xml/test/old/toc/book.css b/dom/xml/test/old/toc/book.css
new file mode 100644
index 0000000000..778c4244c2
--- /dev/null
+++ b/dom/xml/test/old/toc/book.css
@@ -0,0 +1,137 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* The book style must be the first style for our JavaScript to work */
+book {
+ display: block;
+ padding-left: 2em;
+ padding-right: 2em;
+ padding-top: 8px;
+ font-size: 12pt;
+ background-color: lightyellow;
+ font-family: Arial;
+}
+
+book title {
+ font-weight: bold;
+ font-size: 24pt;
+ display: block;
+ text-align: center;
+ margin-top: 12pt;
+ margin-bottom: 3pt;
+}
+
+book subtitle {
+ display: block;
+ font-size:12pt;
+ text-align: center;
+}
+
+book abstract {
+ display: block;
+ margin-top: 3pt;
+}
+
+input {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+chapter {
+ display: block;
+}
+
+chapter title {
+ font-weight: bold;
+ font-size: 16pt;
+ display: block;
+ text-align: left;
+ margin-top: 12pt;
+ margin-bottom: 3pt;
+}
+
+section {
+ display: block;
+}
+
+section title {
+ display: block;
+ font-size: 10pt;
+ text-align: left;
+ margin-top: 12pt;
+ margin-bottom: 3pt;
+}
+
+contents {
+ display: block;
+}
+
+para {
+ display: block;
+ margin-bottom: auto;
+ margin-top: auto;
+ font-size:11pt;
+}
+
+link {
+ display: inline;
+ color: blue;
+ text-decoration: underline;
+ cursor: pointer;
+}
+
+list {
+ display: block;
+ margin-right: 0;
+ margin-bottom: auto;
+ margin-top: auto;
+ list-style-type: disc;
+ margin-left: 40px;
+}
+
+listitem {
+ display: list-item;
+ list-style-position: inside;
+}
+
+emph {
+ font-style: italic;
+ font-weight: bold;
+}
+
+ref {
+ font-style: italic;
+}
+
+heading {
+ font-weight: bold;
+}
+
+navbar {
+ font-family: Arial;
+ font-size: 10pt;
+ display: block;
+ float: right;
+ background-color: #CCE6F3;
+ color: darkblue;
+ width: 10em;
+ margin-right: 0.5em;
+}
+
+navbar title {
+ font-size: 10pt;
+ display: block;
+ background-color: black;
+ color: white;
+ margin-bottom:0px;
+}
+
+navbar content {
+ display: block;
+ padding: 0.3em;
+ border: 1px solid black;
+ font-size: 9pt;
+}
+
diff --git a/dom/xml/test/old/toc/irslogo.gif b/dom/xml/test/old/toc/irslogo.gif
new file mode 100644
index 0000000000..daab0ca3ab
--- /dev/null
+++ b/dom/xml/test/old/toc/irslogo.gif
Binary files differ
diff --git a/dom/xml/test/old/toc/minus.gif b/dom/xml/test/old/toc/minus.gif
new file mode 100644
index 0000000000..8adf8d6add
--- /dev/null
+++ b/dom/xml/test/old/toc/minus.gif
Binary files differ
diff --git a/dom/xml/test/old/toc/plus.gif b/dom/xml/test/old/toc/plus.gif
new file mode 100644
index 0000000000..55446e34c9
--- /dev/null
+++ b/dom/xml/test/old/toc/plus.gif
Binary files differ
diff --git a/dom/xml/test/old/toc/rights.xml b/dom/xml/test/old/toc/rights.xml
new file mode 100644
index 0000000000..520eef3de1
--- /dev/null
+++ b/dom/xml/test/old/toc/rights.xml
@@ -0,0 +1,292 @@
+<?xml version="1.0"?>
+<!-- Our script expects the book.css stylesheet first -->
+<?xml-stylesheet href="book.css" type="text/css"?>
+<?xml-stylesheet href="toc.css" type="text/css"?>
+<!DOCTYPE book [
+<!ATTLIST book id ID #IMPLIED>
+<!ATTLIST chapter id ID #IMPLIED>
+<!ATTLIST section id ID #IMPLIED>
+]>
+<book id="book" xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <html:a name="book"/>
+ <html:script src="toc.js"/>
+ <html:img src="irslogo.gif"/>
+ <navbar>
+ <title>Table of contents</title>
+ <content>
+ To toggle the Table of Contents, click on this button
+ <html:input type="button" value="Contents" onclick="createToc();"/>
+ </content>
+ </navbar>
+
+ <title>Highlights of 1999 Tax Changes</title>
+ <subtitle>(Rev. December 1999)</subtitle>
+
+ <chapter id="chap1">
+ <html:a name="chap1"/>
+ <title>Tax Changes for Individuals</title>
+ <contents>
+ <section id="chap1sec1">
+ <html:a name="chap1sec1"/>
+ <title>Child Tax Credit Increased</title>
+ <contents>
+ <para>
+The maximum child tax credit for each qualifying child will increase from $400 to $500 in 1999.
+ </para>
+ </contents>
+ </section>
+ <section id="chap1sec2">
+ <html:a name="chap1sec2"/>
+ <title>Standard Mileage Rate</title>
+ <contents>
+ <para>
+Beginning April 1, 1999, the optional standard mileage rate for operating your carfor business decreases to 31 cents a mile for each business mile. Until then, the business standard mileage rate of 32 1/2 cents per mile that was in effect for 1998 will continue to apply.
+ </para>
+ </contents>
+ </section>
+ <section id="chap1sec3">
+ <html:a name="chap1sec3"/>
+ <title>Estimated Tax Safe Harbor for Higher Income Individuals</title>
+ <contents>
+ <para>
+For estimated tax payments for tax years beginning in 1999, the safe harbor for higher income individuals (other than farmers and fishermen) has been modified. If your 1998 adjusted gross income was more than $150,000 ($75,000 if you aremarried filing a separate return for 1999), you will have to pay the smaller of 90% of your expected tax for 1999 or 105% (up from 100%) of the tax shown on your 1998 return (provided your 1998 return covered all 12 months) to avoid an estimated tax penalty.
+ </para>
+ <para>
+For more information on estimated tax, see
+ <link xlink:type="simple" xlink:href="http://www.irs.ustreas.gov/prod/forms_pubs/pubs/p505toc.htm" xlink:show="replace" xlink:actuate="user">Publication 505</link>.
+ </para>
+ </contents>
+ </section>
+ <section id="chap1sec4">
+ <html:a name="chap1sec4"/>
+ <title>Self-Employed Health Insurance Deduction</title>
+ <contents>
+ <para>
+For 1999, the health insurance deduction for the self-employed is increased from 45% to 60% of the amount you pay for medical insurance for yourself and your family. For more information, see chapter 10 in
+ <link xlink:type="simple" xlink:href="http://www.irs.ustreas.gov/prod/forms_pubs/pubs/p535toc.htm" xlink:show="replace" xlink:actuate="user">Publication 535</link>.
+ </para>
+ </contents>
+ </section>
+ <section id="chap1sec5">
+ <html:a name="chap1sec5"/>
+ <title>Social Security and Medicare Taxes</title>
+ <contents>
+ <para>
+For 1999, the employer and employee will continue to pay:
+ <list>
+ <listitem>
+1.6.2% each for social security tax (old-age, survivors, and disability insurance), and
+ </listitem>
+ <listitem>
+2.1.45% each for Medicare tax (hospital insurance).
+ </listitem>
+ </list>
+ </para>
+ <para>
+ <heading>Wage limits.</heading>
+For social security tax, the maximum amount of 1999 wages subject to the tax has increased to $72,600. For Medicare tax, all covered 1999 wages are subject to the tax. There is no wage base limit. For information about these taxes, see
+ <link xlink:type="simple" xlink:href="http://www.irs.ustreas.gov/prod/forms_pubs/pubs/p15toc.htm" xlink:show="replace" xlink:actuate="user">Publication 15</link>, <ref>Circular E, Employer's Tax Guide</ref>.
+ </para>
+ </contents>
+ </section>
+ <section id="chap1sec6">
+ <html:a name="chap1sec6"/>
+ <title>Self-Employment Tax</title>
+ <contents>
+ <para>
+The self-employment tax rate on net earnings remains the same for calendar year1999. This rate, 15.3%, is a total of 12.4% for social security (old-age, survivors, and disability insurance), and 2.9% for Medicare (hospital insurance).
+ </para>
+ <para>
+The maximum amount subject to the social security part for tax years beginning in 1999 has increased to $72,600. All net earnings of at least $400 are subject to the Medicare part.
+ </para>
+ </contents>
+ </section>
+ </contents>
+ </chapter>
+
+ <chapter id="chap2">
+ <html:a name="chap2"/>
+ <title>Tax Changes for Businesses</title>
+ <contents>
+ <section id="chap2sec1">
+ <html:a name="chap2sec1"/>
+ <title>Social Security and Medicare Taxes</title>
+ <contents>
+ <para>
+For 1999, the employer and employee will continue to pay:
+ <list>
+ <listitem>
+6.2% each for social security tax (old-age, survivors, and disability insurance), and
+ </listitem>
+ <listitem>
+1.45% each for Medicare tax (hospital insurance).
+ </listitem>
+ </list>
+ </para>
+ <para>
+<heading>Wage limits.</heading> For social security tax, the maximum amount of 1999 wages subject to the tax has increased to $72,600. For Medicare tax, all covered 1999 wages are subject to the tax. There is no wage base limit. For information about these taxes and amounts to withhold, see
+<link xlink:type="simple" xlink:href="http://www.irs.ustreas.gov/prod/forms_pubs/pubs/p15toc.htm" xlink:show="replace" xlink:actuate="user">Publication 15</link>, <ref>Circular E, Employer's TaxGuide</ref>.
+ </para>
+ </contents>
+ </section>
+ <section id="chap2sec2">
+ <html:a name="chap2sec2"/>
+ <title>Employment Tax Deposits</title>
+ <contents>
+ <para>
+Under certain circumstances, the IRS can waive the penalty for a first-time depositor's inadvertent failure to timely deposit employment taxes. For deposits required to be made after January 18, 1999, this waiver is expanded to include the first deposit required to be made after a required change in frequency of a taxpayer's deposits.
+ </para>
+ </contents>
+ </section>
+ <section id="chap2sec3">
+ <html:a name="chap2sec3"/>
+ <title>Electronic Deposit of Taxes</title>
+ <contents>
+ <para>
+If you were first required to deposit taxes by electronic funds transfer after June 30, 1997, the IRS will not impose the penalty for not doing so before July 1, 1999. Previously, the IRS had waived the penalty through December 31, 1998. For information about depositing taxes electronically, see <link xlink:type="simple" xlink:href="http://www.irs.ustreas.gov/prod/forms_pubs/pubs/p15toc.htm" xlink:show="replace" xlink:actuate="user">Publication 15</link>.
+ </para>
+ </contents>
+ </section>
+ <section id="chap2sec4">
+ <html:a name="chap2sec4"/>
+ <title>941 TeleFile</title>
+ <contents>
+ <para>
+Beginning with the first quarter of 1998, many employers were able to file Form941 by phone, toll free. If you receive 941 TeleFile with your Form 941 package, check page TEL-1 of the <ref>941 TeleFile Instructions</ref> to see if you qualify for this quick, convenient, and easy method of filing.
+ </para>
+ </contents>
+ </section>
+ <section id="chap2sec5">
+ <html:a name="chap2sec5"/>
+ <title>941 On-Line</title>
+ <contents>
+ <para>
+In 1998, a limited number of employers were allowed to file Form 941 using commercially available software to create the return and then transmitting the return electronically to IRS through a third party. 941 On-Line uses Electronic Data Interchange (EDI) format. In 1999, IRS expects to make the 941 On-Line filing option available nationwide.
+ </para>
+ </contents>
+ </section>
+ <section id="chap2sec6">
+ <html:a name="chap2sec6"/>
+ <title>Self-Employment Tax </title>
+ <contents>
+ <para>
+The self-employment tax rate on net earnings remains the same for calendar year 1999. This rate, 15.3%, is a total of 12.4% for social security (old-age, survivors,and disability insurance), and 2.9% for Medicare (hospital insurance).
+ </para>
+ <para>
+The maximum amount subject to the social security part for tax years beginning in 1999 has increased to $72,600. All net earnings of at least $400 are subject to the Medicare part.
+ </para>
+ </contents>
+ </section>
+ </contents>
+ </chapter>
+
+ <chapter id="chap3">
+ <html:a name="chap3"/>
+ <title>IRA and other Retirement Plans</title>
+ <contents>
+ <section id="chap3sec1">
+ <html:a name="chap3sec1"/>
+ <title>Hardship Distributions</title>
+ <contents>
+ <para>
+Beginning in 1999, hardship distributions from 401(k) plans and 403(b) plans are not eligible rollover distributions. They cannot be rolled over into a traditional IRA. For more information on traditional IRAs, see <link xlink:type="simple" xlink:href="http://www.irs.ustreas.gov/prod/forms_pubs/pubs/p590toc.htm" xlink:show="replace" xlink:actuate="user">Publication 590</link>.
+ </para>
+ </contents>
+ </section>
+ </contents>
+ </chapter>
+
+ <chapter id="chap4">
+ <html:a name="chap4"/>
+ <title>Gift and Estate Taxes</title>
+ <contents>
+ <section id="chap4sec1">
+ <html:a name="chap4sec1"/>
+ <title>New Deduction From Gross Estate</title>
+ <contents>
+ <para>
+For estates of decedents dying after 1997, the executor can elect to deduct the adjusted value of a qualified family-owned business interest, up to a limited amount, from the gross estate. For more information, see section 2057 of the Internal Revenue Code and the instructions for Schedule T, Form 706, <ref>United States Estate (and Generation-Skipping Transfer) Tax Return</ref>.
+ </para>
+ </contents>
+ </section>
+ <section id="chap4sec2">
+ <html:a name="chap4sec2"/>
+ <title>Suit for Refund</title>
+ <contents>
+ <para>
+Effective July 23, 1998, an executor no longer needs to wait until all the installment payments have been made before filing a suit for refund with a federal district court or the U.S. Court of Federal Claims if the following conditions are met.
+ <list>
+ <listitem>
+The estate consists largely of an interest in a closely-held business.
+ </listitem>
+ <listitem>
+The estate elected to make tax payments through the installment method.
+ </listitem>
+ </list>
+ </para>
+ <para>
+However, all of the following must be true before a suit can be filed.
+ <list>
+ <listitem>
+All installment payments due on or before the date the suit is filed have been made.
+ </listitem>
+ <listitem>
+No accelerated installment payments have been made.
+ </listitem>
+ <listitem>
+No Tax Court case is pending with respect to any estate tax liability.
+ </listitem>
+ <listitem>
+The time for petitioning the Tax Court has passed if a notice of deficiency was issued to the estate regarding its liability for estate tax.
+ </listitem>
+ <listitem>
+No proceeding is pending for a declaratory judgment by the Tax Court on whether the estate is eligible to pay tax in installments.
+ </listitem>
+ </list>
+ </para>
+ <para>
+In addition, the executor must <emph>not</emph>:
+ <list>
+ <listitem>
+Include any previously litigated issues in the current suit for refund, and
+ </listitem>
+ <listitem>
+Discontinue making timely installment payments while the court considers the suit for refund.
+ </listitem>
+ </list>
+ </para>
+ </contents>
+ </section>
+ </contents>
+ </chapter>
+
+ <chapter id="chap5">
+ <html:a name="chap5"/>
+ <title>Excise Tax</title>
+ <contents>
+ <section id="chap5sec1">
+ <html:a name="chap5sec1"/>
+ <title>Air Transportation Taxes</title>
+ <contents>
+ <para>
+For 1999, the tax on the use of international air travel facilities will be $12.20 for both arrivals and departures. In the case of air transportation between the continental United States and Alaska or between Alaska and Hawaii, the use-of-international-facilities tax on departures will be $6.10.
+ </para>
+ </contents>
+ </section>
+ <section id="chap5sec2">
+ <html:a name="chap5sec2"/>
+ <title>Luxury Tax</title>
+ <contents>
+ <para>
+For 1999, the luxury tax on a passenger vehicle is reduced from 7% to 6% of the amount of the sales price that exceeds the base amount. The base amount for 1999 is $36,000.
+ </para>
+ <para>
+The base amount is increased for electric vehicles and clean-fuel vehicles. See <link xlink:type="simple" xlink:href="http://www.irs.ustreas.gov/prod/forms_pubs/pubs/p510toc.htm" xlink:show="replace" xlink:actuate="user">Publication 510</link> for information on these amounts.
+ </para>
+ </contents>
+ </section>
+ </contents>
+ </chapter>
+
+</book>
diff --git a/dom/xml/test/old/toc/toc.css b/dom/xml/test/old/toc/toc.css
new file mode 100644
index 0000000000..99c0c9d327
--- /dev/null
+++ b/dom/xml/test/old/toc/toc.css
@@ -0,0 +1,77 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+toc {
+ position:fixed;
+ top:0;
+ left:0;
+ width:12em;
+ height:100%;
+ border-right: 1px solid black;
+ background-color: #CCE6F3;
+ font-family: Arial;
+ overflow:auto;
+ color: darkblue;
+}
+
+toc > title {
+ display: block;
+ font-size:12pt;
+ font-weight: bold;
+ background-color: black;
+ color:white;
+}
+
+toclink:visited {
+ color: purple;
+}
+
+toclink:active {
+ color: red;
+}
+
+level1 {
+ display: block;
+ font-weight:bold;
+ font-size:12pt;
+ margin-left: 4px;
+ margin-bottom: 2px;
+}
+
+level1 > toclink {
+ list-style-position: inside;
+ text-decoration: none;
+ color: darkblue;
+}
+
+level2 {
+ display: block;
+ font-size:11pt;
+ margin-left: 8px;
+ margin-bottom: 2px;
+}
+
+level2 > toclink {
+ list-style-position: inside;
+ text-decoration: none;
+ color: darkblue;
+}
+
+level3 {
+ display: list-item;
+ font-size: 8pt;
+ margin-left: 12px;
+ margin-bottom: 2px;
+}
+
+level3 > toclink {
+ list-style-position: inside;
+ text-decoration: none;
+ color: darkblue;
+}
+
+toc img {
+ margin-right: 1em;
+}
+
diff --git a/dom/xml/test/old/toc/toc.js b/dom/xml/test/old/toc/toc.js
new file mode 100644
index 0000000000..b1cfbc4959
--- /dev/null
+++ b/dom/xml/test/old/toc/toc.js
@@ -0,0 +1,131 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Event handler for display togglers in Table of Contents
+function toggleDisplay(event) {
+ if (event.target.localName != "img") {
+ return;
+ }
+ var img = event.target;
+ var div = img.nextSibling.nextSibling;
+
+ // Change the display: property of the container to
+ // hide and show the container.
+ if (div.style.display == "none") {
+ div.style.display = "block";
+ img.src = "minus.gif";
+ } else {
+ div.style.display = "none";
+ img.src = "plus.gif";
+ }
+}
+
+// Function that recurses down the tree, looking for
+// structural elements. For each structural element,
+// a corresponding element is created in the table of
+// contents.
+var searchTags = new Array("book", "chapter", "section");
+var tocTags = new Array("level1", "level2", "level3");
+function addToToc(root, tocFrame) {
+ var i;
+ var newTocFrame = tocFrame;
+ var newTocElement = null;
+ var newTocLink = null;
+
+ for (i = 0; i < searchTags.length; i++) {
+ if (root.tagName == searchTags[i]) {
+ // If we've found a structural element, create the
+ // equivalent TOC element.
+ newTocElement = document.createElement(tocTags[i]);
+ // Create the toclink element that is a link to the
+ // corresponding structural element.
+ newTocLink = document.createElement("toclink");
+ newTocLink.setAttributeNS(
+ "http://www.w3.org/1999/xlink",
+ "xlink:type",
+ "simple"
+ );
+ newTocLink.setAttributeNS(
+ "http://www.w3.org/1999/xlink",
+ "xlink:href",
+ "#" + root.getAttribute("id")
+ );
+ newTocLink.setAttributeNS(
+ "http://www.w3.org/1999/xlink",
+ "xlink:show",
+ "replace"
+ );
+ newTocElement.appendChild(newTocLink);
+
+ // Create the image and toggling container in the table of contents
+ if (i < searchTags.length - 1) {
+ var img = document.createElementNS(
+ "http://www.w3.org/1999/xhtml",
+ "img"
+ );
+ img.src = "minus.gif";
+ newTocElement.insertBefore(img, newTocLink);
+
+ newTocFrame = document.createElementNS(
+ "http://www.w3.org/1999/xhtml",
+ "div"
+ );
+ newTocElement.appendChild(newTocFrame);
+ } else {
+ newTocFrame = null;
+ }
+
+ tocFrame.appendChild(newTocElement);
+
+ break;
+ }
+ }
+
+ // Recurse down through the childNodes list
+ for (i = 0; i < root.childNodes.length; i++) {
+ var child = root.childNodes[i];
+ if (child.nodeType == Node.ELEMENT_NODE) {
+ if (newTocLink != null && child.tagName == "title") {
+ var text = child.firstChild.cloneNode(true);
+ newTocLink.appendChild(text);
+ } else {
+ addToToc(child, newTocFrame);
+ }
+ }
+ }
+}
+
+// Create the root table of contents element (a fixed element)
+// and its contents.
+function createToc() {
+ if (!document.getElementsByTagName("toc").length) {
+ var toc = document.createElement("toc");
+ var title = document.createElement("title");
+ title.appendChild(document.createTextNode("Table of Contents"));
+ toc.appendChild(title);
+
+ // Recurse down and build up the document element
+ addToToc(document.documentElement, toc);
+
+ // Since we've created the toc element as a fixed element,
+ // insert a rule that shifts over the document element by
+ // the width of the toc element.
+ document.styleSheets[0].cssRules[0].style.marginLeft = "12em";
+ document.documentElement.appendChild(toc);
+
+ // Attach the event handler for table of contents buttons.
+ // This will only work for content that is already a part
+ // of a document, which is why we had to wait until here
+ // to do this.
+ toc.addEventListener("mouseup", toggleDisplay, 1);
+ } else {
+ // Hide the table of contents.
+ // This is not very intelligent if we have a static document, we should
+ // just hide/show the toc via stylesheet mungling
+ document.documentElement.removeChild(
+ document.getElementsByTagName("toc")[0]
+ );
+ document.styleSheets[0].cssRules[0].style.marginLeft = "0em";
+ }
+}
diff --git a/dom/xml/test/old/xlink/auto.xml b/dom/xml/test/old/xlink/auto.xml
new file mode 100644
index 0000000000..91eb15ff43
--- /dev/null
+++ b/dom/xml/test/old/xlink/auto.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="link.css" type="text/css"?>
+<root xmlns:xlink="http://www.w3.org/1999/xlink">
+ <p>Testing simple XLinks that must fire immediately on load.</p>
+ <mylink xlink:type="simple" xlink:actuate="onLoad" xlink:show="new" xlink:href="resource:/res/samples/test0.html">
+Must not open automatically, illegal</mylink>
+ <mylink xlink:type="simple" xlink:actuate="onLoad" xlink:show="new" xlink:href="http://www.mozilla.org">
+Must open automatically in new window (www.mozilla.org)</mylink>
+ <mylink xlink:type="simple" xlink:actuate="onLoad" xlink:show="new" xlink:href="http://www.mozillazine.org">
+Must open automatically in new window (www.mozillazine.org)</mylink>
+ <mylink xlink:type="simple" xlink:actuate="onLoad" xlink:show="replace" xlink:href="http://www.mozilla.org/mozorg.html">
+Must load automatically in same window - "Refresh" (At a glance)</mylink>
+ <mylink xlink:type="simple" xlink:actuate="onLoad" xlink:show="replace" xlink:href="http://www.netscape.com">
+Must not load automatically, one refresh link fired already (www.netscape.com)</mylink>
+</root>
+
diff --git a/dom/xml/test/old/xlink/link.css b/dom/xml/test/old/xlink/link.css
new file mode 100644
index 0000000000..19dc52198d
--- /dev/null
+++ b/dom/xml/test/old/xlink/link.css
@@ -0,0 +1,22 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+@namespace xlink url(http://www.w3.org/1999/xlink);
+
+root {
+ display: block;
+ padding: +5px;
+}
+
+p {
+ display: block;
+}
+
+mylink {
+ display: block;
+ cursor: pointer;
+ color: blue;
+ text-decoration: underline;
+}
+
diff --git a/dom/xml/test/old/xlink/manual.xml b/dom/xml/test/old/xlink/manual.xml
new file mode 100644
index 0000000000..fd7d49fc17
--- /dev/null
+++ b/dom/xml/test/old/xlink/manual.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="link.css" type="text/css"?>
+<root xmlns:xlink="http://www.w3.org/1999/xlink">
+ <p>Testing manual simple XLinks.</p>
+ <mylink xlink:type="simple" xlink:show="new" xlink:href="resource:/res/samples/test0.html">
+Must not open, illegal</mylink>
+ <mylink xlink:type="simple" xlink:show="new" xlink:href="http://www.mozilla.org">
+Must open in new window (www.mozilla.org)</mylink>
+ <mylink xlink:type="simple" xlink:show="replace" xlink:href="http://www.mozillazine.org">
+Must open in same window (www.mozillazine.org)</mylink>
+ <mylink xlink:type="simple" xlink:show="foo" xlink:href="http://www.mozilla.org/">
+Foo</mylink>
+</root>
+
diff --git a/dom/xml/test/old/xmlbase/xmlbase.css b/dom/xml/test/old/xmlbase/xmlbase.css
new file mode 100644
index 0000000000..a100186bbc
--- /dev/null
+++ b/dom/xml/test/old/xmlbase/xmlbase.css
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+@namespace xlink url(http://www.w3.org/1999/xlink);
+
+title {
+ font-weight: bold;
+ display: block;
+}
+
+xlink|link {
+ color: blue;
+ text-decoration: underline;
+ cursor: pointer;
+ display: inline;
+ padding-left: +5px;
+}
+
+sect1,sect2,sect3 {
+ display: block;
+ padding-left: +20px;
+}
+
+p {
+ display: block;
+ padding-left: +5px;
+} \ No newline at end of file
diff --git a/dom/xml/test/old/xmlbase/xmlbase.xml b/dom/xml/test/old/xmlbase/xmlbase.xml
new file mode 100644
index 0000000000..b4cce1dc51
--- /dev/null
+++ b/dom/xml/test/old/xmlbase/xmlbase.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml-stylesheet href="xmlbase.css" type="text/css"?>
+<root xmlns:xlink="http://www.w3.org/1999/xlink">
+<title>Root: no xml:base</title>
+<xlink:link xlink:type="simple" xlink:href="a.xml">a.xml</xlink:link>
+<p>Expected: &lt;current path>/a.xml</p>
+<sect1 xml:base="http://www.mozilla.org">
+ <title>Sect1: xml:base="http://www.mozilla.org"</title>
+ <xlink:link xlink:type="simple" xlink:href="b.xml">b.xml</xlink:link>
+ <p>Expected: http://www.mozilla.org/b.xml</p>
+ <sect2 xml:base="/base">
+ <title>Sect2: xml:base="/base"</title>
+ <xlink:link xlink:type="simple" xlink:href="c.xml">c.xml</xlink:link>
+ <p>Expected: http://www.mozilla.org/base/c.xml</p>
+ <sect3 xml:base="">
+ <title>Sect3: xml:base=""</title>
+ <xlink:link xlink:type="simple" xlink:href="d.xml">d.xml</xlink:link>
+ <p>Expected: http://www.mozilla.org/base/d.xml</p>
+ </sect3>
+ <sect3 xml:base="/">
+ <title>Sect3: xml:base="/"</title>
+ <xlink:link xlink:type="simple" xlink:href="d-2.xml">d-2.xml</xlink:link>
+ <p>Expected: http://www.mozilla.org/d-2.xml</p>
+ </sect3>
+ <sect3 xml:base="/foobar">
+ <title>Sect3: xml:base="/foobar"</title>
+ <xlink:link xlink:type="simple" xlink:href="e.xml">e.xml</xlink:link>
+ <p>Expected: http://www.mozilla.org/foobar/e.xml</p>
+ </sect3>
+ <sect3 xml:base="ding/dong">
+ <title>Sect3: xml:base="ding/dong"</title>
+ <xlink:link xlink:type="simple" xlink:href="f.xml">f.xml</xlink:link>
+ <p>Expected: http://www.mozilla.org/base/ding/dong/f.xml</p>
+ </sect3>
+ </sect2>
+ <sect2 xml:base="http://www.netscape.com">
+ <title>Sect2: xml:base="http://www.netscape.com"</title>
+ <xlink:link xlink:type="simple" xlink:href="g.xml">g.xml</xlink:link>
+ <p>Expected: http://www.netscape.com/g.xml</p>
+ </sect2>
+ <sect2 xml:base="http://www.netscape.com">
+ <title>Sect2: xml:base="http://www.netscape.com"</title>
+ <xlink:link xlink:type="simple" xlink:href="http://www.mozilla.org/foobar/h.xml">http://www.mozilla.org/foobar/h.xml</xlink:link>
+ <p>Expected: http://www.mozilla.org/foobar/h.xml</p>
+ </sect2>
+ <sect2 xml:base="http://www.netscape.com">
+ <title>Sect2: xml:base="http://www.netscape.com"</title>
+ <xlink:link xlink:type="simple" xlink:href="i.xml" xml:base="wow">i.xml, this element has xml:base="wow"</xlink:link>
+ <p>Expected: http://www.netscape.com/wow/i.xml</p>
+ </sect2>
+</sect1>
+<sect1 xml:base="nothere">
+ <title>Sect1: xml:base="nothere"</title>
+ <xlink:link xlink:type="simple" xlink:href="j.xml">j.xml</xlink:link>
+ <p>Expected: &lt;current path>/nothere/j.xml</p>
+</sect1>
+<sect1 xml:base="/not">
+ <title>Sect1: xml:base="/not"</title>
+ <xlink:link xlink:type="simple" xlink:href="k.xml">k.xml</xlink:link>
+ <p>Expected: file:///not/k.xml</p>
+</sect1>
+<sect1 xml:base="http://foobar.com/ä ö/">
+ <title>Sect1: xml:base="http://foobar.com/ä ö/"</title>
+ <xlink:link xlink:type="simple" xlink:href="l.xml">l.xml</xlink:link>
+ <p>Expected: http://foobar.com/%E4%20%F6/l.xml</p>
+</sect1>
+<sect1 xml:base="http://foobar.com/ /%20/">
+ <title>Sect1: xml:base="http://foobar.com/ /%20/"</title>
+ <xlink:link xlink:type="simple" xlink:href="m.xml">m.xml</xlink:link>
+ <p>Expected: http://foobar.com/%20/%20/m.xml</p>
+</sect1>
+<sect1 xml:base="chrome://navigator">
+ <title>Sect1: xml:base="chrome://navigator"</title>
+ <xlink:link xlink:type="simple" xlink:href="n.xml">n.xml</xlink:link>
+ <p>Expected: |current path|/n.xml because chrome URL is not allowed</p>
+ <sect2 xml:base="http://www.mozilla.org">
+ <title>Sect2: xml:base="http://www.mozilla.org"</title>
+ <xlink:link xlink:type="simple" xlink:href="o.xml" xml:base="chrome://navigator">o.xml, this element has xml:base="chrome://navigator"</xlink:link>
+ <p>Expected: http://www.mozilla.org/o.xml because chrome base is not allowed</p>
+ </sect2>
+</sect1>
+</root> \ No newline at end of file
diff --git a/dom/xml/test/test_bug232004.xhtml b/dom/xml/test/test_bug232004.xhtml
new file mode 100644
index 0000000000..a15129a71e
--- /dev/null
+++ b/dom/xml/test/test_bug232004.xhtml
@@ -0,0 +1,38 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=232004
+-->
+<head>
+ <title>Test for Bug 232004</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"/>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=232004">Mozilla Bug 232004</a>
+<p id="display">
+ <input id="one" type="text" />
+ <input style="display: none" id="two" type="text" />
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+
+/** Test for Bug 232004 **/
+
+$("one").focus();
+is(document.activeElement, $("one"), "node one should be focused");
+
+$("two").focus();
+isnot(document.activeElement, $("two"),
+ "node two has display:none and should not take focus");
+
+]]>
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/xml/test/test_bug293347.html b/dom/xml/test/test_bug293347.html
new file mode 100644
index 0000000000..6db99bdaa3
--- /dev/null
+++ b/dom/xml/test/test_bug293347.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=293347
+-->
+<head>
+ <title>Test for Bug 293347</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=293347">Mozilla Bug 293347</a>
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function done(iframe) {
+ let win = iframe.contentWindow;
+ is(win.document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "div")
+ .length, 2, "doc still intact");
+ is(win.document.body.namespaceURI, "http://www.w3.org/1999/xhtml",
+ "doc body still intact");
+ is(win.didThrow, true, "doc.write throwing");
+ SimpleTest.finish();
+}
+
+</script>
+<iframe src="file_bug293347.xml" onload="done(this)"></iframe>
+</pre>
+</body>
+</html>
diff --git a/dom/xml/test/test_bug343870.xhtml b/dom/xml/test/test_bug343870.xhtml
new file mode 100644
index 0000000000..7fa625211b
--- /dev/null
+++ b/dom/xml/test/test_bug343870.xhtml
@@ -0,0 +1,39 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=343870
+-->
+<head>
+ <title>Test for Bug 343870</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=343870">Mozilla Bug 343870</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+
+/** Test for Bug 343870 **/
+function doTest() {
+ var dataDoc = document.getElementById("d").contentDocument;
+ is(dataDoc.getElementById("lf").firstChild.data, "\n");
+ is(dataDoc.getElementById("cr").firstChild.data, "\n");
+ is(dataDoc.getElementById("crlf").firstChild.data, "\n");
+ is(dataDoc.getElementById("escapedcr").firstChild.data, "\r");
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(doTest);
+addLoadEvent(SimpleTest.finish);
+
+]]>
+</script>
+</pre>
+<iframe id="d" src="file_bug343870.xml"></iframe>
+</body>
+</html>
+
diff --git a/dom/xml/test/test_bug355213.xhtml b/dom/xml/test/test_bug355213.xhtml
new file mode 100644
index 0000000000..3376a4b8b3
--- /dev/null
+++ b/dom/xml/test/test_bug355213.xhtml
@@ -0,0 +1,35 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=355213
+-->
+<head>
+ <title>Test for Bug 355213</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=355213">Mozilla Bug 355213</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+
+/** Test for Bug 355213 **/
+ var firstWidth = document.getElementById('display').offsetWidth;
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(
+ function() {
+ is(firstWidth, document.getElementById('test').offsetWidth,
+ "Width should not change");
+ });
+ addLoadEvent(SimpleTest.finish);
+
+]]>
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/xml/test/test_bug691215.html b/dom/xml/test/test_bug691215.html
new file mode 100644
index 0000000000..70a5f7b719
--- /dev/null
+++ b/dom/xml/test/test_bug691215.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=691215
+-->
+<head>
+ <title>Test for Bug 691215</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=691215">Mozilla Bug 691215</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 691215 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var BASE_URI = "http://mochi.test:8888/tests/dom/xml/test/";
+var url = BASE_URI + "file_bug691215.xml";
+var w;
+
+addLoadEvent(function() {
+ // Need a separate window because we do not prettyprint in iframes. This is
+ // why this test can't be a crashtest.
+ w = window.open(url);
+ // Need to poll for load completion, sadly
+ setTimeout(checker, 0);
+});
+
+function checker() {
+ if (w.location.href != url ||
+ w.document.readyState != "complete") {
+ setTimeout(checker, 0);
+ return;
+ }
+ var doc = w.document;
+ var n = doc.createElement("span");
+ doc.replaceChild(n, doc.documentElement);
+ w.close();
+ ok(1, "Hey, we got here, that's good");
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>