| // Copyright 2018 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. | |
| #include "core/fxcrt/xml/cfx_xmlelement.h" | |
| #include "core/fxcrt/xml/cfx_xmlchardata.h" | |
| #include "core/fxcrt/xml/cfx_xmldocument.h" | |
| #include "core/fxcrt/xml/cfx_xmltext.h" | |
| #include "testing/gtest/include/gtest/gtest.h" | |
| #include "testing/string_write_stream.h" | |
| TEST(CFX_XMLElementTest, GetType) { | |
| CFX_XMLElement node(L"node"); | |
| EXPECT_EQ(CFX_XMLNode::Type::kElement, node.GetType()); | |
| } | |
| TEST(CFX_XMLElementTest, GetName) { | |
| CFX_XMLElement node(L"node"); | |
| EXPECT_EQ(L"node", node.GetName()); | |
| } | |
| TEST(CFX_XMLElementTest, GetLocalTagName) { | |
| CFX_XMLElement node1(L"node1"); | |
| EXPECT_EQ(L"node1", node1.GetLocalTagName()); | |
| CFX_XMLElement node2(L"test:node2"); | |
| EXPECT_EQ(L"node2", node2.GetLocalTagName()); | |
| } | |
| TEST(CFX_XMLElementTest, GetNamespacePrefix) { | |
| CFX_XMLElement node1(L"node1"); | |
| EXPECT_EQ(L"", node1.GetNamespacePrefix()); | |
| CFX_XMLElement node2(L"test:node2"); | |
| EXPECT_EQ(L"test", node2.GetNamespacePrefix()); | |
| } | |
| TEST(CFX_XMLElementTest, GetNamespaceURI) { | |
| CFX_XMLElement node1(L"node1"); | |
| EXPECT_EQ(L"", node1.GetNamespaceURI()); | |
| node1.SetAttribute(L"xmlns", L"https://example.org/ns1"); | |
| EXPECT_EQ(L"https://example.org/ns1", node1.GetNamespaceURI()); | |
| CFX_XMLElement node2(L"test:node2"); | |
| EXPECT_EQ(L"", node2.GetNamespaceURI()); | |
| node2.SetAttribute(L"xmlns", L"https://example.org/ns2"); | |
| EXPECT_EQ(L"", node2.GetNamespaceURI()); | |
| node2.SetAttribute(L"xmlns:test", L"https://example.org/ns2"); | |
| EXPECT_EQ(L"https://example.org/ns2", node2.GetNamespaceURI()); | |
| } | |
| TEST(CFX_XMLElementTest, Attributes) { | |
| CFX_XMLElement node(L"test:node"); | |
| node.SetAttribute(L"first", L"one"); | |
| node.SetAttribute(L"second", L"two"); | |
| ASSERT_TRUE(node.HasAttribute(L"first")); | |
| EXPECT_EQ(L"one", node.GetAttribute(L"first")); | |
| ASSERT_TRUE(node.HasAttribute(L"second")); | |
| EXPECT_EQ(L"two", node.GetAttribute(L"second")); | |
| ASSERT_EQ(2U, node.GetAttributes().size()); | |
| node.RemoveAttribute(L"first"); | |
| EXPECT_FALSE(node.HasAttribute(L"first")); | |
| ASSERT_EQ(1U, node.GetAttributes().size()); | |
| } | |
| TEST(CFX_XMLElementTest, Clone) { | |
| CFX_XMLDocument doc; | |
| CFX_XMLElement node(L"test:node"); | |
| node.SetAttribute(L"first", L"one"); | |
| node.SetAttribute(L"second", L"two"); | |
| node.SetAttribute(L"xmlns:test", L"https://example.org/test"); | |
| CFX_XMLText text_child1(L"Text Child"); | |
| node.AppendLastChild(&text_child1); | |
| CFX_XMLElement node_child1(L"Node child"); | |
| node.AppendLastChild(&node_child1); | |
| CFX_XMLNode* clone = node.Clone(&doc); | |
| EXPECT_TRUE(clone != nullptr); | |
| ASSERT_EQ(CFX_XMLNode::Type::kElement, clone->GetType()); | |
| CFX_XMLElement* inst = ToXMLElement(clone); | |
| EXPECT_EQ(L"test:node", inst->GetName()); | |
| EXPECT_EQ(L"node", inst->GetLocalTagName()); | |
| EXPECT_EQ(L"test", inst->GetNamespacePrefix()); | |
| EXPECT_EQ(L"https://example.org/test", inst->GetNamespaceURI()); | |
| ASSERT_TRUE(inst->HasAttribute(L"first")); | |
| EXPECT_EQ(L"one", inst->GetAttribute(L"first")); | |
| ASSERT_TRUE(inst->HasAttribute(L"second")); | |
| EXPECT_EQ(L"two", inst->GetAttribute(L"second")); | |
| // Only clone the Text node, so expect only one child. | |
| ASSERT_TRUE(inst->GetFirstChild() != nullptr); | |
| EXPECT_TRUE(inst->GetFirstChild()->GetNextSibling() == nullptr); | |
| ASSERT_EQ(CFX_XMLNode::Type::kText, inst->GetFirstChild()->GetType()); | |
| auto* text = ToXMLText(inst->GetFirstChild()); | |
| EXPECT_EQ(L"Text Child", text->GetText()); | |
| } | |
| TEST(CFX_XMLElementTest, Save) { | |
| auto stream = pdfium::MakeRetain<StringWriteStream>(); | |
| CFX_XMLElement node(L"root"); | |
| node.Save(stream); | |
| EXPECT_EQ("<root />\n", stream->ToString()); | |
| } | |
| TEST(CFX_XMLElementTest, SaveWithAttributes) { | |
| auto stream = pdfium::MakeRetain<StringWriteStream>(); | |
| CFX_XMLElement node(L"root"); | |
| node.SetAttribute(L"first", L"one"); | |
| node.SetAttribute(L"second", L"two"); | |
| node.Save(stream); | |
| EXPECT_EQ("<root first=\"one\" second=\"two\" />\n", stream->ToString()); | |
| } | |
| TEST(CFX_XMLElementTest, SaveWithChildren) { | |
| auto stream = pdfium::MakeRetain<StringWriteStream>(); | |
| CFX_XMLElement node(L"node"); | |
| CFX_XMLText text_child1(L"Text Child 1"); | |
| node.AppendLastChild(&text_child1); | |
| CFX_XMLElement node_child1(L"node-child"); | |
| node.AppendLastChild(&node_child1); | |
| CFX_XMLText text_child2(L"Text Child 2"); | |
| node_child1.AppendLastChild(&text_child2); | |
| CFX_XMLCharData char_data1(L"Char Data"); | |
| node.AppendLastChild(&char_data1); | |
| node.Save(stream); | |
| EXPECT_EQ( | |
| "<node>\n" | |
| "Text Child 1" | |
| "<node-child>\nText Child 2</node-child>\n" | |
| "<![CDATA[Char Data]]>" | |
| "</node>\n", | |
| stream->ToString()); | |
| } | |
| TEST(CFX_XMLElementTest, SaveWithNamespace) { | |
| auto stream = pdfium::MakeRetain<StringWriteStream>(); | |
| CFX_XMLElement node(L"test:root"); | |
| node.SetAttribute(L"xmlns:test", L"https://example.org/ns1"); | |
| node.Save(stream); | |
| EXPECT_EQ("<test:root xmlns:test=\"https://example.org/ns1\" />\n", | |
| stream->ToString()); | |
| } | |
| TEST(CFX_XMLElementTest, GetFirstChildNamed) { | |
| CFX_XMLElement node(L"node"); | |
| CFX_XMLElement node_child1(L"node-child"); | |
| node.AppendLastChild(&node_child1); | |
| auto* found = node.GetFirstChildNamed(L"node-child"); | |
| EXPECT_TRUE(found != nullptr); | |
| EXPECT_EQ(&node_child1, found); | |
| } | |
| TEST(CFX_XMLElementTest, GetFirstChildNamedMissing) { | |
| CFX_XMLElement node(L"node"); | |
| CFX_XMLElement node_child1(L"node-child"); | |
| node.AppendLastChild(&node_child1); | |
| auto* found = node.GetFirstChildNamed(L"node-sibling"); | |
| EXPECT_TRUE(found == nullptr); | |
| } | |
| TEST(CFX_XMLElementTest, GetNthChildNamed) { | |
| CFX_XMLElement node(L"node"); | |
| CFX_XMLElement node_child1(L"node-child"); | |
| CFX_XMLElement node_child2(L"node-child"); | |
| CFX_XMLElement node_child3(L"node-child"); | |
| node.AppendLastChild(&node_child1); | |
| node.AppendLastChild(&node_child2); | |
| node.AppendLastChild(&node_child3); | |
| auto* found = node.GetNthChildNamed(L"node-child", 2); | |
| EXPECT_TRUE(found != nullptr); | |
| EXPECT_EQ(&node_child3, found); | |
| } | |
| TEST(CFX_XMLElementTest, GetNthChildNamedMissingChild) { | |
| CFX_XMLElement node(L"node"); | |
| CFX_XMLElement node_child1(L"node-child"); | |
| CFX_XMLElement node_child2(L"node-child"); | |
| CFX_XMLElement node_child3(L"node-child"); | |
| node.AppendLastChild(&node_child1); | |
| node.AppendLastChild(&node_child2); | |
| node.AppendLastChild(&node_child3); | |
| auto* found = node.GetNthChildNamed(L"node-child", 5); | |
| EXPECT_TRUE(found == nullptr); | |
| } | |
| TEST(CFX_XMLElementTest, GetTextData) { | |
| CFX_XMLElement node(L"node"); | |
| CFX_XMLText text_child1(L"Text Child 1"); | |
| node.AppendLastChild(&text_child1); | |
| CFX_XMLElement node_child1(L"Node child"); | |
| node.AppendLastChild(&node_child1); | |
| CFX_XMLText text_child2(L"Text Child 2"); | |
| node_child1.AppendLastChild(&text_child2); | |
| CFX_XMLCharData char_data1(L"Char Data"); | |
| node.AppendLastChild(&char_data1); | |
| EXPECT_EQ(L"Text Child 1Char Data", node.GetTextData()); | |
| } |