1 // Copyright 2017 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxcrt/xml/cfx_xmlelement.h"
8 
9 #include <utility>
10 
11 #include "core/fxcrt/cfx_widetextbuf.h"
12 #include "core/fxcrt/fx_extension.h"
13 #include "core/fxcrt/xml/cfx_xmlchardata.h"
14 #include "core/fxcrt/xml/cfx_xmltext.h"
15 #include "third_party/base/ptr_util.h"
16 #include "third_party/base/stl_util.h"
17 
CFX_XMLElement(const WideString & wsTag)18 CFX_XMLElement::CFX_XMLElement(const WideString& wsTag)
19     : CFX_XMLAttributeNode(wsTag) {}
20 
~CFX_XMLElement()21 CFX_XMLElement::~CFX_XMLElement() {}
22 
GetType() const23 FX_XMLNODETYPE CFX_XMLElement::GetType() const {
24   return FX_XMLNODE_Element;
25 }
26 
Clone()27 std::unique_ptr<CFX_XMLNode> CFX_XMLElement::Clone() {
28   auto pClone = pdfium::MakeUnique<CFX_XMLElement>(GetName());
29   pClone->SetAttributes(GetAttributes());
30 
31   WideString wsText;
32   CFX_XMLNode* pChild = m_pChild;
33   while (pChild) {
34     switch (pChild->GetType()) {
35       case FX_XMLNODE_Text:
36         wsText += static_cast<CFX_XMLText*>(pChild)->GetText();
37         break;
38       default:
39         break;
40     }
41     pChild = pChild->m_pNext;
42   }
43   pClone->SetTextData(wsText);
44   return std::move(pClone);
45 }
46 
GetLocalTagName() const47 WideString CFX_XMLElement::GetLocalTagName() const {
48   auto pos = GetName().Find(L':');
49   return pos.has_value()
50              ? GetName().Right(GetName().GetLength() - pos.value() - 1)
51              : GetName();
52 }
53 
GetNamespacePrefix() const54 WideString CFX_XMLElement::GetNamespacePrefix() const {
55   auto pos = GetName().Find(L':');
56   return pos.has_value() ? GetName().Left(pos.value()) : WideString();
57 }
58 
GetNamespaceURI() const59 WideString CFX_XMLElement::GetNamespaceURI() const {
60   WideString wsAttri(L"xmlns");
61   WideString wsPrefix = GetNamespacePrefix();
62   if (wsPrefix.GetLength() > 0) {
63     wsAttri += L":";
64     wsAttri += wsPrefix;
65   }
66 
67   auto* pNode = static_cast<const CFX_XMLNode*>(this);
68   while (pNode) {
69     if (pNode->GetType() != FX_XMLNODE_Element)
70       break;
71 
72     auto* pElement = static_cast<const CFX_XMLElement*>(pNode);
73     if (!pElement->HasAttribute(wsAttri)) {
74       pNode = pNode->GetNodeItem(CFX_XMLNode::Parent);
75       continue;
76     }
77     return pElement->GetString(wsAttri);
78   }
79   return WideString();
80 }
81 
GetTextData() const82 WideString CFX_XMLElement::GetTextData() const {
83   CFX_WideTextBuf buffer;
84   CFX_XMLNode* pChild = m_pChild;
85   while (pChild) {
86     switch (pChild->GetType()) {
87       case FX_XMLNODE_Text:
88       case FX_XMLNODE_CharData:
89         buffer << static_cast<CFX_XMLText*>(pChild)->GetText();
90         break;
91       default:
92         break;
93     }
94     pChild = pChild->m_pNext;
95   }
96   return buffer.MakeString();
97 }
98 
SetTextData(const WideString & wsText)99 void CFX_XMLElement::SetTextData(const WideString& wsText) {
100   if (wsText.GetLength() < 1)
101     return;
102   InsertChildNode(new CFX_XMLText(wsText));
103 }
104