| // 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" | |
| // static | |
| std::unique_ptr<CXML_Element> CXML_Element::Parse(const void* pBuffer, | |
| size_t size) { | |
| CXML_Parser parser; | |
| if (!parser.Init(static_cast<const uint8_t*>(pBuffer), size)) | |
| 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() {} | |
| CXML_Element* CXML_Element::AsElement() { | |
| return this; | |
| } | |
| const CXML_Element* CXML_Element::AsElement() const { | |
| return this; | |
| } | |
| 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; | |
| } | |
| uint32_t CXML_Element::CountElements(const CFX_ByteStringC& space, | |
| const CFX_ByteStringC& tag) const { | |
| int count = 0; | |
| for (const auto& pChild : m_Children) { | |
| const CXML_Element* pKid = pChild->AsElement(); | |
| if (pKid && pKid->m_TagName == tag && | |
| (space.IsEmpty() || pKid->m_QSpaceName == space)) { | |
| count++; | |
| } | |
| } | |
| return count; | |
| } | |
| CXML_Object* CXML_Element::GetChild(uint32_t index) const { | |
| return index < m_Children.size() ? m_Children[index].get() : nullptr; | |
| } | |
| CXML_Element* CXML_Element::GetElement(const CFX_ByteStringC& space, | |
| const CFX_ByteStringC& tag, | |
| int nth) const { | |
| if (nth < 0) | |
| return nullptr; | |
| for (const auto& pChild : m_Children) { | |
| CXML_Element* pKid = pChild->AsElement(); | |
| if (pKid && pKid->m_TagName == tag && | |
| (space.IsEmpty() || pKid->m_QSpaceName == space)) { | |
| if (nth-- == 0) | |
| return pKid; | |
| } | |
| } | |
| return nullptr; | |
| } | |
| uint32_t CXML_Element::FindElement(CXML_Element* pElement) const { | |
| int index = 0; | |
| for (const auto& pChild : m_Children) { | |
| CXML_Element* pKid = pChild->AsElement(); | |
| if (pKid && pKid == pElement) | |
| 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; | |
| } |