dbf8724170991ba7094392ce9462a410d7163b48
[platform/upstream/libxml++.git] / examples / dom_xinclude / main.cc
1 /* Copyright (C) 2012 The libxml++ development team
2  *
3  * This file is part of libxml++.
4  *
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.
9  *
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.
14  *
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/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <libxml++/libxml++.h>
24 #include <iostream>
25 #include <stdlib.h>
26
27 void print_node(const xmlpp::Node* node, unsigned int indentation = 0)
28 {
29   const Glib::ustring indent(indentation, ' ');
30
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);
34
35   //Let's ignore the indenting - you don't always want to do this.
36   if (nodeText && nodeText->is_white_space())
37     return;
38
39   const auto nodename = node->get_name();
40
41   if (!nodeText && !nodeComment && !nodename.empty()) //Let's not say "name: text".
42   {
43     const auto namespace_prefix = node->get_namespace_prefix();
44
45     std::cout << indent << "Node name = ";
46     if (!namespace_prefix.empty())
47       std::cout << namespace_prefix << ":";
48     std::cout << nodename << std::endl;
49   }
50   else if (nodeText) //Let's say when it's text.
51   {
52     std::cout << indent << "Text Node" << std::endl;
53   }
54
55   //Treat the various node types differently:
56   if (nodeText)
57   {
58     std::cout << indent << "text = \"" << nodeText->get_content() << "\"" << std::endl;
59   }
60   else if (nodeComment)
61   {
62     std::cout << indent << "comment = " << nodeComment->get_content() << std::endl;
63   }
64   else if (nodeContent)
65   {
66     std::cout << indent << "content = " << nodeContent->get_content() << std::endl;
67   }
68   else if (const xmlpp::Element* nodeElement = dynamic_cast<const xmlpp::Element*>(node))
69   {
70     //A normal Element node:
71     std::cout << indent << "     Element line = " << node->get_line() << std::endl;
72
73     //Print attributes:
74     for (const auto& attribute : nodeElement->get_attributes())
75     {
76       const auto namespace_prefix = attribute->get_namespace_prefix();
77
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;
82     }
83
84     const auto attribute = nodeElement->get_attribute("title");
85     if (attribute)
86     {
87       std::cout << indent << "title = " << attribute->get_value() << std::endl;
88     }
89   }
90   else if (dynamic_cast<const xmlpp::XIncludeStart*>(node))
91   {
92     std::cout << indent << "     " << "XIncludeStart line = " << node->get_line() << std::endl;
93   }
94   else if (dynamic_cast<const xmlpp::XIncludeEnd*>(node))
95   {
96     std::cout << indent << "     " << "XIncludeEnd" << std::endl;
97   }
98
99   if (!nodeContent)
100   {
101     //Recurse through child nodes:
102     for(const auto& child : node->get_children())
103     {
104       print_node(child, indentation + 2); //recursive
105     }
106   }
107 }
108
109 int main(int argc, char* argv[])
110 {
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(""));
114
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;
121
122   int argi = 1;
123   while (argc > argi && *argv[argi] == '-') // option
124   {
125     switch (*(argv[argi]+1))
126     {
127       case 'v':
128         validate = true;
129         break;
130       case 't':
131        set_throw_messages = true;
132        throw_messages = true;
133        break;
134       case 'e':
135        set_throw_messages = true;
136        throw_messages = false;
137        break;
138       case 'E':
139         substitute_entities = false;
140         break;
141       case 'X':
142         generate_xinclude_nodes = false;
143         break;
144       case 'B':
145         fixup_base_uris = false;
146         break;
147      default:
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;
155        return EXIT_FAILURE;
156      }
157      argi++;
158   }
159   std::string filepath;
160   if (argc > argi)
161     filepath = argv[argi]; //Allow the user to specify a different XML file to parse.
162   else
163     filepath = "example.xml";
164
165   try
166   {
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);
174     if (parser)
175     {
176       //Walk the tree:
177       auto pNode = parser.get_document()->get_root_node(); //deleted by DomParser.
178       print_node(pNode);
179
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;
184
185       std::cout << ">>>>> After XInclude processing with xmlpp::Document::process_xinclude(): "
186                 << std::endl << std::endl;
187       pNode = parser.get_document()->get_root_node();
188       print_node(pNode);
189
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;
194     }
195
196     parser.set_xinclude_options(true, generate_xinclude_nodes, fixup_base_uris);
197     parser.parse_file(filepath);
198     if (parser)
199     {
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());
203
204       const auto whole = parser.get_document()->write_to_string();
205       std::cout << std::endl << whole << std::endl;
206     }
207   }
208   catch (const std::exception& ex)
209   {
210     std::cerr << "Exception caught: " << ex.what() << std::endl;
211     return EXIT_FAILURE;
212   }
213
214   return EXIT_SUCCESS;
215 }
216