summaryrefslogtreecommitdiff
path: root/core/fxcrt/xml/cxml_element.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fxcrt/xml/cxml_element.cpp')
-rw-r--r--core/fxcrt/xml/cxml_element.cpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/core/fxcrt/xml/cxml_element.cpp b/core/fxcrt/xml/cxml_element.cpp
new file mode 100644
index 0000000000..20ad54e88c
--- /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;
+}