Move core/fxcrt XML files to core/fxcrt/xml

This CL moves the other XML files contained in core/fxcrt into the
core/fxcrt/xml directory to contain all the fxcrt XML files in one place.

Change-Id: I9faefb1f311bf167b75dfbb7b9b52f25515e3c31
Reviewed-on: https://pdfium-review.googlesource.com/3378
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index f695be9..53facc8 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -781,15 +781,20 @@
     "core/fxcrt/fx_ucd.h",
     "core/fxcrt/fx_ucddata.cpp",
     "core/fxcrt/fx_unicode.cpp",
-    "core/fxcrt/fx_xml.h",
-    "core/fxcrt/fx_xml_composer.cpp",
-    "core/fxcrt/fx_xml_parser.cpp",
     "core/fxcrt/fxcrt_posix.cpp",
     "core/fxcrt/fxcrt_posix.h",
     "core/fxcrt/fxcrt_stream.cpp",
     "core/fxcrt/fxcrt_windows.cpp",
     "core/fxcrt/fxcrt_windows.h",
-    "core/fxcrt/xml_int.h",
+    "core/fxcrt/xml/cxml_attritem.cpp",
+    "core/fxcrt/xml/cxml_attritem.h",
+    "core/fxcrt/xml/cxml_attrmap.cpp",
+    "core/fxcrt/xml/cxml_attrmap.h",
+    "core/fxcrt/xml/cxml_content.h",
+    "core/fxcrt/xml/cxml_element.cpp",
+    "core/fxcrt/xml/cxml_element.h",
+    "core/fxcrt/xml/cxml_parser.cpp",
+    "core/fxcrt/xml/cxml_parser.h",
   ]
   configs += [ ":pdfium_core_config" ]
   visibility += [ "third_party:*" ]
diff --git a/core/fpdfdoc/cpdf_metadata.cpp b/core/fpdfdoc/cpdf_metadata.cpp
index 5e3acbe..3780d15 100644
--- a/core/fpdfdoc/cpdf_metadata.cpp
+++ b/core/fpdfdoc/cpdf_metadata.cpp
@@ -9,7 +9,7 @@
 #include "core/fpdfapi/parser/cpdf_document.h"
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
-#include "core/fxcrt/fx_xml.h"
+#include "core/fxcrt/xml/cxml_element.h"
 
 CPDF_Metadata::CPDF_Metadata(CPDF_Document* pDoc) {
   CPDF_Dictionary* pRoot = pDoc->GetRoot();
diff --git a/core/fxcrt/fx_xml_composer.cpp b/core/fxcrt/fx_xml_composer.cpp
deleted file mode 100644
index 637d64c..0000000
--- a/core/fxcrt/fx_xml_composer.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "core/fxcrt/xml_int.h"
-
-#include "core/fxcrt/fx_xml.h"
-
-void FX_XML_SplitQualifiedName(const CFX_ByteStringC& bsFullName,
-                               CFX_ByteStringC& bsSpace,
-                               CFX_ByteStringC& bsName) {
-  if (bsFullName.IsEmpty())
-    return;
-
-  FX_STRSIZE iStart = bsFullName.Find(':');
-  if (iStart == -1) {
-    bsName = bsFullName;
-  } else {
-    bsSpace = bsFullName.Mid(0, iStart);
-    bsName = bsFullName.Mid(iStart + 1);
-  }
-}
-
-void CXML_Element::SetTag(const CFX_ByteStringC& qTagName) {
-  ASSERT(!qTagName.IsEmpty());
-  CFX_ByteStringC bsSpace;
-  CFX_ByteStringC bsName;
-  FX_XML_SplitQualifiedName(qTagName, bsSpace, bsName);
-  m_QSpaceName = bsSpace;
-  m_TagName = bsName;
-}
diff --git a/core/fxcrt/xml/cxml_attritem.cpp b/core/fxcrt/xml/cxml_attritem.cpp
new file mode 100644
index 0000000..8e55799
--- /dev/null
+++ b/core/fxcrt/xml/cxml_attritem.cpp
@@ -0,0 +1,12 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcrt/xml/cxml_attritem.h"
+
+bool CXML_AttrItem::Matches(const CFX_ByteString& space,
+                            const CFX_ByteString& name) const {
+  return (space.IsEmpty() || m_QSpaceName == space) && m_AttrName == name;
+}
diff --git a/core/fxcrt/xml/cxml_attritem.h b/core/fxcrt/xml/cxml_attritem.h
new file mode 100644
index 0000000..63305e8
--- /dev/null
+++ b/core/fxcrt/xml/cxml_attritem.h
@@ -0,0 +1,21 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCRT_XML_CXML_ATTRITEM_H_
+#define CORE_FXCRT_XML_CXML_ATTRITEM_H_
+
+#include "core/fxcrt/fx_string.h"
+
+class CXML_AttrItem {
+ public:
+  bool Matches(const CFX_ByteString& space, const CFX_ByteString& name) const;
+
+  CFX_ByteString m_QSpaceName;
+  CFX_ByteString m_AttrName;
+  CFX_WideString m_Value;
+};
+
+#endif  // CORE_FXCRT_XML_CXML_ATTRITEM_H_
diff --git a/core/fxcrt/xml/cxml_attrmap.cpp b/core/fxcrt/xml/cxml_attrmap.cpp
new file mode 100644
index 0000000..8d226fe
--- /dev/null
+++ b/core/fxcrt/xml/cxml_attrmap.cpp
@@ -0,0 +1,50 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcrt/xml/cxml_attrmap.h"
+
+#include "third_party/base/ptr_util.h"
+#include "third_party/base/stl_util.h"
+
+CXML_AttrMap::CXML_AttrMap() {}
+
+CXML_AttrMap::~CXML_AttrMap() {}
+
+const CFX_WideString* CXML_AttrMap::Lookup(const CFX_ByteString& space,
+                                           const CFX_ByteString& name) const {
+  if (!m_pMap)
+    return nullptr;
+
+  for (const auto& item : *m_pMap) {
+    if (item.Matches(space, name))
+      return &item.m_Value;
+  }
+  return nullptr;
+}
+
+void CXML_AttrMap::SetAt(const CFX_ByteString& space,
+                         const CFX_ByteString& name,
+                         const CFX_WideString& value) {
+  if (!m_pMap)
+    m_pMap = pdfium::MakeUnique<std::vector<CXML_AttrItem>>();
+
+  for (CXML_AttrItem& item : *m_pMap) {
+    if (item.Matches(space, name)) {
+      item.m_Value = value;
+      return;
+    }
+  }
+
+  m_pMap->push_back({space, name, CFX_WideString(value)});
+}
+
+int CXML_AttrMap::GetSize() const {
+  return m_pMap ? pdfium::CollectionSize<int>(*m_pMap) : 0;
+}
+
+CXML_AttrItem& CXML_AttrMap::GetAt(int index) const {
+  return (*m_pMap)[index];
+}
diff --git a/core/fxcrt/xml/cxml_attrmap.h b/core/fxcrt/xml/cxml_attrmap.h
new file mode 100644
index 0000000..0a026d3
--- /dev/null
+++ b/core/fxcrt/xml/cxml_attrmap.h
@@ -0,0 +1,33 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCRT_XML_CXML_ATTRMAP_H_
+#define CORE_FXCRT_XML_CXML_ATTRMAP_H_
+
+#include <memory>
+#include <vector>
+
+#include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/xml/cxml_attritem.h"
+
+class CXML_AttrMap {
+ public:
+  CXML_AttrMap();
+  ~CXML_AttrMap();
+
+  const CFX_WideString* Lookup(const CFX_ByteString& space,
+                               const CFX_ByteString& name) const;
+  int GetSize() const;
+  CXML_AttrItem& GetAt(int index) const;
+
+  void SetAt(const CFX_ByteString& space,
+             const CFX_ByteString& name,
+             const CFX_WideString& value);
+
+  std::unique_ptr<std::vector<CXML_AttrItem>> m_pMap;
+};
+
+#endif  // CORE_FXCRT_XML_CXML_ATTRMAP_H_
diff --git a/core/fxcrt/xml/cxml_content.h b/core/fxcrt/xml/cxml_content.h
new file mode 100644
index 0000000..261c622
--- /dev/null
+++ b/core/fxcrt/xml/cxml_content.h
@@ -0,0 +1,23 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCRT_XML_CXML_CONTENT_H_
+#define CORE_FXCRT_XML_CXML_CONTENT_H_
+
+class CXML_Content {
+ public:
+  CXML_Content() : m_bCDATA(false), m_Content() {}
+
+  void Set(bool bCDATA, const CFX_WideStringC& content) {
+    m_bCDATA = bCDATA;
+    m_Content = content;
+  }
+
+  bool m_bCDATA;
+  CFX_WideString m_Content;
+};
+
+#endif  // CORE_FXCRT_XML_CXML_CONTENT_H_
diff --git a/core/fxcrt/xml/cxml_element.cpp b/core/fxcrt/xml/cxml_element.cpp
new file mode 100644
index 0000000..20ad54e
--- /dev/null
+++ b/core/fxcrt/xml/cxml_element.cpp
@@ -0,0 +1,228 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcrt/xml/cxml_element.h"
+
+#include "core/fxcrt/xml/cxml_content.h"
+#include "core/fxcrt/xml/cxml_parser.h"
+
+CXML_Element::CXML_Element(const CXML_Element* pParent,
+                           const CFX_ByteStringC& qSpace,
+                           const CFX_ByteStringC& tagname)
+    : m_pParent(pParent), m_QSpaceName(qSpace), m_TagName(tagname) {}
+
+CXML_Element::~CXML_Element() {
+  Empty();
+}
+
+void CXML_Element::Empty() {
+  RemoveChildren();
+}
+void CXML_Element::RemoveChildren() {
+  for (const ChildRecord& record : m_Children) {
+    if (record.type == Content) {
+      delete static_cast<CXML_Content*>(record.child);
+    } else if (record.type == Element) {
+      CXML_Element* child = static_cast<CXML_Element*>(record.child);
+      child->RemoveChildren();
+      delete child;
+    }
+  }
+  m_Children.clear();
+}
+CFX_ByteString CXML_Element::GetTagName(bool bQualified) const {
+  if (!bQualified || m_QSpaceName.IsEmpty()) {
+    return m_TagName;
+  }
+  CFX_ByteString bsTag = m_QSpaceName;
+  bsTag += ":";
+  bsTag += m_TagName;
+  return bsTag;
+}
+
+CFX_ByteString CXML_Element::GetNamespace(bool bQualified) const {
+  return bQualified ? m_QSpaceName : GetNamespaceURI(m_QSpaceName);
+}
+
+CFX_ByteString CXML_Element::GetNamespaceURI(
+    const CFX_ByteString& qName) const {
+  const CFX_WideString* pwsSpace;
+  const CXML_Element* pElement = this;
+  do {
+    if (qName.IsEmpty())
+      pwsSpace = pElement->m_AttrMap.Lookup("", "xmlns");
+    else
+      pwsSpace = pElement->m_AttrMap.Lookup("xmlns", qName);
+    if (pwsSpace)
+      break;
+
+    pElement = pElement->GetParent();
+  } while (pElement);
+  return pwsSpace ? pwsSpace->UTF8Encode() : CFX_ByteString();
+}
+
+void CXML_Element::GetAttrByIndex(int index,
+                                  CFX_ByteString& space,
+                                  CFX_ByteString& name,
+                                  CFX_WideString& value) const {
+  if (index < 0 || index >= m_AttrMap.GetSize())
+    return;
+
+  CXML_AttrItem& item = m_AttrMap.GetAt(index);
+  space = item.m_QSpaceName;
+  name = item.m_AttrName;
+  value = item.m_Value;
+}
+
+bool CXML_Element::HasAttr(const CFX_ByteStringC& name) const {
+  CFX_ByteStringC bsSpace;
+  CFX_ByteStringC bsName;
+  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
+  return !!m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName));
+}
+
+bool CXML_Element::GetAttrValue(const CFX_ByteStringC& name,
+                                CFX_WideString& attribute) const {
+  CFX_ByteStringC bsSpace;
+  CFX_ByteStringC bsName;
+  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
+  return GetAttrValue(bsSpace, bsName, attribute);
+}
+
+bool CXML_Element::GetAttrValue(const CFX_ByteStringC& space,
+                                const CFX_ByteStringC& name,
+                                CFX_WideString& attribute) const {
+  const CFX_WideString* pValue =
+      m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
+  if (!pValue)
+    return false;
+
+  attribute = *pValue;
+  return true;
+}
+
+bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& name,
+                                  int& attribute) const {
+  CFX_ByteStringC bsSpace;
+  CFX_ByteStringC bsName;
+  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
+  const CFX_WideString* pwsValue =
+      m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName));
+  if (!pwsValue)
+    return false;
+
+  attribute = pwsValue->GetInteger();
+  return true;
+}
+
+bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& space,
+                                  const CFX_ByteStringC& name,
+                                  int& attribute) const {
+  const CFX_WideString* pwsValue =
+      m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
+  if (!pwsValue)
+    return false;
+
+  attribute = pwsValue->GetInteger();
+  return true;
+}
+
+bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& name,
+                                float& attribute) const {
+  CFX_ByteStringC bsSpace;
+  CFX_ByteStringC bsName;
+  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
+  return GetAttrFloat(bsSpace, bsName, attribute);
+}
+
+bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& space,
+                                const CFX_ByteStringC& name,
+                                float& attribute) const {
+  const CFX_WideString* pValue =
+      m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
+  if (!pValue)
+    return false;
+
+  attribute = pValue->GetFloat();
+  return true;
+}
+
+CXML_Element::ChildType CXML_Element::GetChildType(uint32_t index) const {
+  return index < m_Children.size() ? m_Children[index].type : Invalid;
+}
+
+CFX_WideString CXML_Element::GetContent(uint32_t index) const {
+  if (index < m_Children.size() && m_Children[index].type == Content) {
+    CXML_Content* pContent =
+        static_cast<CXML_Content*>(m_Children[index].child);
+    if (pContent)
+      return pContent->m_Content;
+  }
+  return CFX_WideString();
+}
+
+CXML_Element* CXML_Element::GetElement(uint32_t index) const {
+  if (index < m_Children.size() && m_Children[index].type == Element)
+    return static_cast<CXML_Element*>(m_Children[index].child);
+  return nullptr;
+}
+
+uint32_t CXML_Element::CountElements(const CFX_ByteStringC& space,
+                                     const CFX_ByteStringC& tag) const {
+  int count = 0;
+  for (const ChildRecord& record : m_Children) {
+    if (record.type != Element)
+      continue;
+
+    CXML_Element* pKid = static_cast<CXML_Element*>(record.child);
+    if ((space.IsEmpty() || pKid->m_QSpaceName == space) &&
+        pKid->m_TagName == tag) {
+      count++;
+    }
+  }
+  return count;
+}
+
+CXML_Element* CXML_Element::GetElement(const CFX_ByteStringC& space,
+                                       const CFX_ByteStringC& tag,
+                                       int index) const {
+  if (index < 0)
+    return nullptr;
+
+  for (const ChildRecord& record : m_Children) {
+    if (record.type != Element)
+      continue;
+
+    CXML_Element* pKid = static_cast<CXML_Element*>(record.child);
+    if ((space.IsEmpty() || pKid->m_QSpaceName == space) &&
+        pKid->m_TagName == tag) {
+      if (index-- == 0)
+        return pKid;
+    }
+  }
+  return nullptr;
+}
+
+uint32_t CXML_Element::FindElement(CXML_Element* pChild) const {
+  int index = 0;
+  for (const ChildRecord& record : m_Children) {
+    if (record.type == Element &&
+        static_cast<CXML_Element*>(record.child) == pChild) {
+      return index;
+    }
+    ++index;
+  }
+  return 0xFFFFFFFF;
+}
+
+void CXML_Element::SetTag(const CFX_ByteStringC& qTagName) {
+  ASSERT(!qTagName.IsEmpty());
+  CFX_ByteStringC bsSpace;
+  CFX_ByteStringC bsName;
+  FX_XML_SplitQualifiedName(qTagName, bsSpace, bsName);
+  m_QSpaceName = bsSpace;
+  m_TagName = bsName;
+}
diff --git a/core/fxcrt/fx_xml.h b/core/fxcrt/xml/cxml_element.h
similarity index 79%
rename from core/fxcrt/fx_xml.h
rename to core/fxcrt/xml/cxml_element.h
index 0b0de23..2e18e18 100644
--- a/core/fxcrt/fx_xml.h
+++ b/core/fxcrt/xml/cxml_element.h
@@ -4,51 +4,14 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#ifndef CORE_FXCRT_FX_XML_H_
-#define CORE_FXCRT_FX_XML_H_
+#ifndef CORE_FXCRT_XML_CXML_ELEMENT_H_
+#define CORE_FXCRT_XML_CXML_ELEMENT_H_
 
 #include <memory>
 #include <vector>
 
 #include "core/fxcrt/fx_basic.h"
-
-class CXML_AttrItem {
- public:
-  bool Matches(const CFX_ByteString& space, const CFX_ByteString& name) const;
-
-  CFX_ByteString m_QSpaceName;
-  CFX_ByteString m_AttrName;
-  CFX_WideString m_Value;
-};
-
-class CXML_AttrMap {
- public:
-  CXML_AttrMap();
-  ~CXML_AttrMap();
-
-  const CFX_WideString* Lookup(const CFX_ByteString& space,
-                               const CFX_ByteString& name) const;
-  int GetSize() const;
-  CXML_AttrItem& GetAt(int index) const;
-
-  void SetAt(const CFX_ByteString& space,
-             const CFX_ByteString& name,
-             const CFX_WideString& value);
-
-  std::unique_ptr<std::vector<CXML_AttrItem>> m_pMap;
-};
-
-class CXML_Content {
- public:
-  CXML_Content() : m_bCDATA(false), m_Content() {}
-  void Set(bool bCDATA, const CFX_WideStringC& content) {
-    m_bCDATA = bCDATA;
-    m_Content = content;
-  }
-
-  bool m_bCDATA;
-  CFX_WideString m_Content;
-};
+#include "core/fxcrt/xml/cxml_attrmap.h"
 
 class CXML_Element {
  public:
@@ -144,7 +107,10 @@
   void RemoveChildren();
   void RemoveChild(uint32_t index);
 
- protected:
+ private:
+  friend class CXML_Parser;
+  friend class CXML_Composer;
+
   struct ChildRecord {
     ChildType type;
     void* child;  // CXML_Element and CXML_Content lack a common ancestor.
@@ -155,9 +121,6 @@
   CFX_ByteString m_TagName;
   CXML_AttrMap m_AttrMap;
   std::vector<ChildRecord> m_Children;
-
-  friend class CXML_Parser;
-  friend class CXML_Composer;
 };
 
-#endif  // CORE_FXCRT_FX_XML_H_
+#endif  // CORE_FXCRT_XML_CXML_ELEMENT_H_
diff --git a/core/fxcrt/fx_xml_parser.cpp b/core/fxcrt/xml/cxml_parser.cpp
similarity index 70%
rename from core/fxcrt/fx_xml_parser.cpp
rename to core/fxcrt/xml/cxml_parser.cpp
index da4815b..be48b7a 100644
--- a/core/fxcrt/fx_xml_parser.cpp
+++ b/core/fxcrt/xml/cxml_parser.cpp
@@ -9,8 +9,9 @@
 #include <vector>
 
 #include "core/fxcrt/fx_ext.h"
-#include "core/fxcrt/fx_xml.h"
-#include "core/fxcrt/xml_int.h"
+#include "core/fxcrt/xml/cxml_content.h"
+#include "core/fxcrt/xml/cxml_element.h"
+#include "core/fxcrt/xml/cxml_parser.h"
 #include "third_party/base/ptr_util.h"
 #include "third_party/base/stl_util.h"
 
@@ -211,6 +212,21 @@
 
 }  // namespace
 
+void FX_XML_SplitQualifiedName(const CFX_ByteStringC& bsFullName,
+                               CFX_ByteStringC& bsSpace,
+                               CFX_ByteStringC& bsName) {
+  if (bsFullName.IsEmpty())
+    return;
+
+  FX_STRSIZE iStart = bsFullName.Find(':');
+  if (iStart == -1) {
+    bsName = bsFullName;
+  } else {
+    bsSpace = bsFullName.Mid(0, iStart);
+    bsName = bsFullName.Mid(iStart + 1);
+  }
+}
+
 CXML_Parser::CXML_Parser()
     : m_nOffset(0),
       m_pBuffer(nullptr),
@@ -662,257 +678,3 @@
     return nullptr;
   return parser.ParseElement(nullptr, false);
 }
-
-CXML_Element::CXML_Element(const CXML_Element* pParent,
-                           const CFX_ByteStringC& qSpace,
-                           const CFX_ByteStringC& tagname)
-    : m_pParent(pParent), m_QSpaceName(qSpace), m_TagName(tagname) {}
-
-CXML_Element::~CXML_Element() {
-  Empty();
-}
-
-void CXML_Element::Empty() {
-  RemoveChildren();
-}
-void CXML_Element::RemoveChildren() {
-  for (const ChildRecord& record : m_Children) {
-    if (record.type == Content) {
-      delete static_cast<CXML_Content*>(record.child);
-    } else if (record.type == Element) {
-      CXML_Element* child = static_cast<CXML_Element*>(record.child);
-      child->RemoveChildren();
-      delete child;
-    }
-  }
-  m_Children.clear();
-}
-CFX_ByteString CXML_Element::GetTagName(bool bQualified) const {
-  if (!bQualified || m_QSpaceName.IsEmpty()) {
-    return m_TagName;
-  }
-  CFX_ByteString bsTag = m_QSpaceName;
-  bsTag += ":";
-  bsTag += m_TagName;
-  return bsTag;
-}
-
-CFX_ByteString CXML_Element::GetNamespace(bool bQualified) const {
-  return bQualified ? m_QSpaceName : GetNamespaceURI(m_QSpaceName);
-}
-
-CFX_ByteString CXML_Element::GetNamespaceURI(
-    const CFX_ByteString& qName) const {
-  const CFX_WideString* pwsSpace;
-  const CXML_Element* pElement = this;
-  do {
-    if (qName.IsEmpty())
-      pwsSpace = pElement->m_AttrMap.Lookup("", "xmlns");
-    else
-      pwsSpace = pElement->m_AttrMap.Lookup("xmlns", qName);
-    if (pwsSpace)
-      break;
-
-    pElement = pElement->GetParent();
-  } while (pElement);
-  return pwsSpace ? pwsSpace->UTF8Encode() : CFX_ByteString();
-}
-
-void CXML_Element::GetAttrByIndex(int index,
-                                  CFX_ByteString& space,
-                                  CFX_ByteString& name,
-                                  CFX_WideString& value) const {
-  if (index < 0 || index >= m_AttrMap.GetSize())
-    return;
-
-  CXML_AttrItem& item = m_AttrMap.GetAt(index);
-  space = item.m_QSpaceName;
-  name = item.m_AttrName;
-  value = item.m_Value;
-}
-
-bool CXML_Element::HasAttr(const CFX_ByteStringC& name) const {
-  CFX_ByteStringC bsSpace;
-  CFX_ByteStringC bsName;
-  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
-  return !!m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName));
-}
-
-bool CXML_Element::GetAttrValue(const CFX_ByteStringC& name,
-                                CFX_WideString& attribute) const {
-  CFX_ByteStringC bsSpace;
-  CFX_ByteStringC bsName;
-  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
-  return GetAttrValue(bsSpace, bsName, attribute);
-}
-
-bool CXML_Element::GetAttrValue(const CFX_ByteStringC& space,
-                                const CFX_ByteStringC& name,
-                                CFX_WideString& attribute) const {
-  const CFX_WideString* pValue =
-      m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
-  if (!pValue)
-    return false;
-
-  attribute = *pValue;
-  return true;
-}
-
-bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& name,
-                                  int& attribute) const {
-  CFX_ByteStringC bsSpace;
-  CFX_ByteStringC bsName;
-  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
-  const CFX_WideString* pwsValue =
-      m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName));
-  if (!pwsValue)
-    return false;
-
-  attribute = pwsValue->GetInteger();
-  return true;
-}
-
-bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& space,
-                                  const CFX_ByteStringC& name,
-                                  int& attribute) const {
-  const CFX_WideString* pwsValue =
-      m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
-  if (!pwsValue)
-    return false;
-
-  attribute = pwsValue->GetInteger();
-  return true;
-}
-
-bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& name,
-                                float& attribute) const {
-  CFX_ByteStringC bsSpace;
-  CFX_ByteStringC bsName;
-  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
-  return GetAttrFloat(bsSpace, bsName, attribute);
-}
-
-bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& space,
-                                const CFX_ByteStringC& name,
-                                float& attribute) const {
-  const CFX_WideString* pValue =
-      m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
-  if (!pValue)
-    return false;
-
-  attribute = pValue->GetFloat();
-  return true;
-}
-
-CXML_Element::ChildType CXML_Element::GetChildType(uint32_t index) const {
-  return index < m_Children.size() ? m_Children[index].type : Invalid;
-}
-
-CFX_WideString CXML_Element::GetContent(uint32_t index) const {
-  if (index < m_Children.size() && m_Children[index].type == Content) {
-    CXML_Content* pContent =
-        static_cast<CXML_Content*>(m_Children[index].child);
-    if (pContent)
-      return pContent->m_Content;
-  }
-  return CFX_WideString();
-}
-
-CXML_Element* CXML_Element::GetElement(uint32_t index) const {
-  if (index < m_Children.size() && m_Children[index].type == Element)
-    return static_cast<CXML_Element*>(m_Children[index].child);
-  return nullptr;
-}
-
-uint32_t CXML_Element::CountElements(const CFX_ByteStringC& space,
-                                     const CFX_ByteStringC& tag) const {
-  int count = 0;
-  for (const ChildRecord& record : m_Children) {
-    if (record.type != Element)
-      continue;
-
-    CXML_Element* pKid = static_cast<CXML_Element*>(record.child);
-    if ((space.IsEmpty() || pKid->m_QSpaceName == space) &&
-        pKid->m_TagName == tag) {
-      count++;
-    }
-  }
-  return count;
-}
-
-CXML_Element* CXML_Element::GetElement(const CFX_ByteStringC& space,
-                                       const CFX_ByteStringC& tag,
-                                       int index) const {
-  if (index < 0)
-    return nullptr;
-
-  for (const ChildRecord& record : m_Children) {
-    if (record.type != Element)
-      continue;
-
-    CXML_Element* pKid = static_cast<CXML_Element*>(record.child);
-    if ((space.IsEmpty() || pKid->m_QSpaceName == space) &&
-        pKid->m_TagName == tag) {
-      if (index-- == 0)
-        return pKid;
-    }
-  }
-  return nullptr;
-}
-
-uint32_t CXML_Element::FindElement(CXML_Element* pChild) const {
-  int index = 0;
-  for (const ChildRecord& record : m_Children) {
-    if (record.type == Element &&
-        static_cast<CXML_Element*>(record.child) == pChild) {
-      return index;
-    }
-    ++index;
-  }
-  return 0xFFFFFFFF;
-}
-
-bool CXML_AttrItem::Matches(const CFX_ByteString& space,
-                            const CFX_ByteString& name) const {
-  return (space.IsEmpty() || m_QSpaceName == space) && m_AttrName == name;
-}
-
-CXML_AttrMap::CXML_AttrMap() {}
-
-CXML_AttrMap::~CXML_AttrMap() {}
-
-const CFX_WideString* CXML_AttrMap::Lookup(const CFX_ByteString& space,
-                                           const CFX_ByteString& name) const {
-  if (!m_pMap)
-    return nullptr;
-
-  for (const auto& item : *m_pMap) {
-    if (item.Matches(space, name))
-      return &item.m_Value;
-  }
-  return nullptr;
-}
-
-void CXML_AttrMap::SetAt(const CFX_ByteString& space,
-                         const CFX_ByteString& name,
-                         const CFX_WideString& value) {
-  if (!m_pMap)
-    m_pMap = pdfium::MakeUnique<std::vector<CXML_AttrItem>>();
-
-  for (CXML_AttrItem& item : *m_pMap) {
-    if (item.Matches(space, name)) {
-      item.m_Value = value;
-      return;
-    }
-  }
-
-  m_pMap->push_back({space, name, CFX_WideString(value)});
-}
-
-int CXML_AttrMap::GetSize() const {
-  return m_pMap ? pdfium::CollectionSize<int>(*m_pMap) : 0;
-}
-
-CXML_AttrItem& CXML_AttrMap::GetAt(int index) const {
-  return (*m_pMap)[index];
-}
diff --git a/core/fxcrt/xml_int.h b/core/fxcrt/xml/cxml_parser.h
similarity index 92%
rename from core/fxcrt/xml_int.h
rename to core/fxcrt/xml/cxml_parser.h
index 96a7da9..37f14e9 100644
--- a/core/fxcrt/xml_int.h
+++ b/core/fxcrt/xml/cxml_parser.h
@@ -4,8 +4,8 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#ifndef CORE_FXCRT_XML_INT_H_
-#define CORE_FXCRT_XML_INT_H_
+#ifndef CORE_FXCRT_XML_CXML_PARSER_H_
+#define CORE_FXCRT_XML_CXML_PARSER_H_
 
 #include <algorithm>
 #include <memory>
@@ -52,4 +52,4 @@
                                CFX_ByteStringC& bsSpace,
                                CFX_ByteStringC& bsName);
 
-#endif  // CORE_FXCRT_XML_INT_H_
+#endif  // CORE_FXCRT_XML_CXML_PARSER_H_
diff --git a/fpdfsdk/fpdf_ext.cpp b/fpdfsdk/fpdf_ext.cpp
index 3bcb0c0..2db4aaf 100644
--- a/fpdfsdk/fpdf_ext.cpp
+++ b/fpdfsdk/fpdf_ext.cpp
@@ -16,7 +16,7 @@
 #include "core/fpdfdoc/cpdf_metadata.h"
 #include "core/fxcrt/fx_basic.h"
 #include "core/fxcrt/fx_memory.h"
-#include "core/fxcrt/fx_xml.h"
+#include "core/fxcrt/xml/cxml_element.h"
 #include "fpdfsdk/fsdk_define.h"
 #include "third_party/base/ptr_util.h"
 
diff --git a/fpdfsdk/pdfwindow/PWL_Edit.cpp b/fpdfsdk/pdfwindow/PWL_Edit.cpp
index 4b9e0d2..1212d7f 100644
--- a/fpdfsdk/pdfwindow/PWL_Edit.cpp
+++ b/fpdfsdk/pdfwindow/PWL_Edit.cpp
@@ -13,7 +13,7 @@
 #include "core/fpdfapi/font/cpdf_font.h"
 #include "core/fpdfdoc/cpvt_word.h"
 #include "core/fxcrt/fx_safe_types.h"
-#include "core/fxcrt/fx_xml.h"
+#include "core/fxcrt/xml/cxml_element.h"
 #include "core/fxge/cfx_graphstatedata.h"
 #include "core/fxge/cfx_pathdata.h"
 #include "core/fxge/cfx_renderdevice.h"
diff --git a/xfa/fgas/crt/cfgas_formatstring.cpp b/xfa/fgas/crt/cfgas_formatstring.cpp
index 57882da..9123b5c 100644
--- a/xfa/fgas/crt/cfgas_formatstring.cpp
+++ b/xfa/fgas/crt/cfgas_formatstring.cpp
@@ -11,7 +11,7 @@
 
 #include "core/fxcrt/cfx_decimal.h"
 #include "core/fxcrt/fx_ext.h"
-#include "core/fxcrt/fx_xml.h"
+#include "core/fxcrt/xml/cxml_element.h"
 
 #define FX_LOCALECATEGORY_DateHash 0xbde9abde
 #define FX_LOCALECATEGORY_TimeHash 0x2d71b00f
diff --git a/xfa/fxfa/parser/cxfa_localemgr.cpp b/xfa/fxfa/parser/cxfa_localemgr.cpp
index ec29c56..b082857 100644
--- a/xfa/fxfa/parser/cxfa_localemgr.cpp
+++ b/xfa/fxfa/parser/cxfa_localemgr.cpp
@@ -12,7 +12,7 @@
 #include <utility>
 
 #include "core/fxcodec/fx_codec.h"
-#include "core/fxcrt/fx_xml.h"
+#include "core/fxcrt/xml/cxml_element.h"
 #include "core/fxge/cfx_gemodule.h"
 #include "xfa/fxfa/parser/cxfa_node.h"
 #include "xfa/fxfa/parser/cxfa_nodelocale.h"
diff --git a/xfa/fxfa/parser/cxfa_nodelocale.cpp b/xfa/fxfa/parser/cxfa_nodelocale.cpp
index 1280b61..78b0cef 100644
--- a/xfa/fxfa/parser/cxfa_nodelocale.cpp
+++ b/xfa/fxfa/parser/cxfa_nodelocale.cpp
@@ -8,7 +8,7 @@
 
 #include <utility>
 
-#include "core/fxcrt/fx_xml.h"
+#include "core/fxcrt/xml/cxml_element.h"
 #include "xfa/fxfa/parser/cxfa_document.h"
 #include "xfa/fxfa/parser/cxfa_localemgr.h"
 #include "xfa/fxfa/parser/cxfa_node.h"
diff --git a/xfa/fxfa/parser/cxfa_xmllocale.cpp b/xfa/fxfa/parser/cxfa_xmllocale.cpp
index aa5c942..dd1d7cd 100644
--- a/xfa/fxfa/parser/cxfa_xmllocale.cpp
+++ b/xfa/fxfa/parser/cxfa_xmllocale.cpp
@@ -8,7 +8,7 @@
 
 #include <utility>
 
-#include "core/fxcrt/fx_xml.h"
+#include "core/fxcrt/xml/cxml_element.h"
 #include "xfa/fxfa/parser/cxfa_document.h"
 #include "xfa/fxfa/parser/cxfa_localemgr.h"
 #include "xfa/fxfa/parser/cxfa_nodelocale.h"