diff options
Diffstat (limited to 'core/fxcrt/xml/cxml_element.cpp')
-rw-r--r-- | core/fxcrt/xml/cxml_element.cpp | 228 |
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; +} |