1 /* Copyright (C) 2012 The libxml++ development team
3 * This file is part of libxml++.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
23 #include <libxml++/libxml++.h>
27 void print_node(const xmlpp::Node* node, unsigned int indentation = 0)
29 const Glib::ustring indent(indentation, ' ');
31 const auto nodeContent = dynamic_cast<const xmlpp::ContentNode*>(node);
32 const auto nodeText = dynamic_cast<const xmlpp::TextNode*>(node);
33 const auto nodeComment = dynamic_cast<const xmlpp::CommentNode*>(node);
35 //Let's ignore the indenting - you don't always want to do this.
36 if (nodeText && nodeText->is_white_space())
39 const auto nodename = node->get_name();
41 if (!nodeText && !nodeComment && !nodename.empty()) //Let's not say "name: text".
43 const auto namespace_prefix = node->get_namespace_prefix();
45 std::cout << indent << "Node name = ";
46 if (!namespace_prefix.empty())
47 std::cout << namespace_prefix << ":";
48 std::cout << nodename << std::endl;
50 else if (nodeText) //Let's say when it's text.
52 std::cout << indent << "Text Node" << std::endl;
55 //Treat the various node types differently:
58 std::cout << indent << "text = \"" << nodeText->get_content() << "\"" << std::endl;
62 std::cout << indent << "comment = " << nodeComment->get_content() << std::endl;
66 std::cout << indent << "content = " << nodeContent->get_content() << std::endl;
68 else if (const xmlpp::Element* nodeElement = dynamic_cast<const xmlpp::Element*>(node))
70 //A normal Element node:
71 std::cout << indent << " Element line = " << node->get_line() << std::endl;
74 for (const auto& attribute : nodeElement->get_attributes())
76 const auto namespace_prefix = attribute->get_namespace_prefix();
78 std::cout << indent << " Attribute ";
79 if (!namespace_prefix.empty())
80 std::cout << namespace_prefix << ":";
81 std::cout << attribute->get_name() << " = " << attribute->get_value() << std::endl;
84 const auto attribute = nodeElement->get_attribute("title");
87 std::cout << indent << "title = " << attribute->get_value() << std::endl;
90 else if (dynamic_cast<const xmlpp::XIncludeStart*>(node))
92 std::cout << indent << " " << "XIncludeStart line = " << node->get_line() << std::endl;
94 else if (dynamic_cast<const xmlpp::XIncludeEnd*>(node))
96 std::cout << indent << " " << "XIncludeEnd" << std::endl;
101 //Recurse through child nodes:
102 for(const auto& child : node->get_children())
104 print_node(child, indentation + 2); //recursive
109 int main(int argc, char* argv[])
111 // Set the global C++ locale to the user-configured locale,
112 // so we can use std::cout with UTF-8, via Glib::ustring, without exceptions.
113 std::locale::global(std::locale(""));
115 bool validate = false;
116 bool set_throw_messages = false;
117 bool throw_messages = false;
118 bool substitute_entities = true;
119 bool generate_xinclude_nodes = true;
120 bool fixup_base_uris = true;
123 while (argc > argi && *argv[argi] == '-') // option
125 switch (*(argv[argi]+1))
131 set_throw_messages = true;
132 throw_messages = true;
135 set_throw_messages = true;
136 throw_messages = false;
139 substitute_entities = false;
142 generate_xinclude_nodes = false;
145 fixup_base_uris = false;
148 std::cout << "Usage: " << argv[0] << " [options]... [filename]" << std::endl
149 << " -v Validate" << std::endl
150 << " -t Throw messages in an exception" << std::endl
151 << " -e Write messages to stderr" << std::endl
152 << " -E Do not substitute entities" << std::endl
153 << " -X Do not generate XInclude nodes" << std::endl
154 << " -B Do not fix up base URIs" << std::endl;
159 std::string filepath;
161 filepath = argv[argi]; //Allow the user to specify a different XML file to parse.
163 filepath = "example.xml";
167 xmlpp::DomParser parser;
168 parser.set_validate(validate);
169 if (set_throw_messages)
170 parser.set_throw_messages(throw_messages);
171 //We can have the text resolved/unescaped automatically.
172 parser.set_substitute_entities(substitute_entities);
173 parser.parse_file(filepath);
177 auto pNode = parser.get_document()->get_root_node(); //deleted by DomParser.
180 std::cout << std::endl << ">>>>> Number of XInclude substitutions: "
181 << parser.get_document()->process_xinclude(
182 generate_xinclude_nodes, fixup_base_uris)
183 << std::endl << std::endl;
185 std::cout << ">>>>> After XInclude processing with xmlpp::Document::process_xinclude(): "
186 << std::endl << std::endl;
187 pNode = parser.get_document()->get_root_node();
190 // xmlpp::Document::write_to_string() does not write XIncludeStart and
191 // XIncludeEnd nodes.
192 const auto whole = parser.get_document()->write_to_string();
193 std::cout << std::endl << whole << std::endl;
196 parser.set_xinclude_options(true, generate_xinclude_nodes, fixup_base_uris);
197 parser.parse_file(filepath);
200 std::cout << ">>>>> After XInclude processing with xmlpp::DomParser::parse_file(): "
201 << std::endl << std::endl;
202 print_node(parser.get_document()->get_root_node());
204 const auto whole = parser.get_document()->write_to_string();
205 std::cout << std::endl << whole << std::endl;
208 catch (const std::exception& ex)
210 std::cerr << "Exception caught: " << ex.what() << std::endl;