4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2002, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* xml.c - A GObject wrapper for libxml documents */
28 #include <libxml/parser.h>
35 static gpointer parent_class
= NULL
;
37 /* Static prototypes */
38 static xmlNode
*best_lang(xmlNode
*first
);
39 static void xml_wrapper_finialize(GObject
*object
);
40 static void xml_wrapper_class_init(gpointer gclass
, gpointer data
);
41 static void xml_wrapper_init(GTypeInstance
*object
, gpointer gclass
);
42 static GType
xml_wrapper_get_type(void);
44 /****************************************************************
45 * EXTERNAL INTERFACE *
46 ****************************************************************/
48 XMLwrapper
*xml_new(const char *pathname
)
55 doc
= xmlParseFile(pathname
);
57 return NULL
; /* Bad XML */
60 xml_data
= g_object_new(xml_wrapper_get_type(), NULL
);
66 /* Return the first child of the root node with this name */
67 xmlNode
*xml_get_section(XMLwrapper
*xml
, const gchar
*ns
, const gchar
*name
)
69 g_return_val_if_fail(xml
!= NULL
, NULL
);
70 g_return_val_if_fail(xml
->doc
!= NULL
, NULL
);
72 return get_subnode(xmlDocGetRootElement(xml
->doc
), ns
, name
);
75 /* Return the (first) child of this node with the given name.
77 * If there are several consecutive nodes with the same name but different
78 * xml:lang attributes, then the one matching the current locale is used,
79 * or the first one if none match.
81 xmlNode
*get_subnode(xmlNode
*node
, const char *namespaceURI
, const char *name
)
83 for (node
= node
->xmlChildrenNode
; node
; node
= node
->next
)
85 if (node
->type
!= XML_ELEMENT_NODE
)
88 if (strcmp(node
->name
, name
))
91 if (node
->ns
== NULL
|| namespaceURI
== NULL
)
93 if (node
->ns
== NULL
&& namespaceURI
== NULL
)
94 return best_lang(node
);
98 if (strcmp(node
->ns
->href
, namespaceURI
) == 0)
99 return best_lang(node
);
105 /****************************************************************
106 * INTERNAL FUNCTIONS *
107 ****************************************************************/
109 /* Taking this node and each directly following node with the same name,
110 * return the one which matches the current LANG.
111 * Return the node itself if nothing matches.
113 static xmlNode
*best_lang(xmlNode
*first
)
115 xmlNode
*node
= first
;
116 const char *target_lang
= current_lang
? current_lang
: "en";
118 g_return_val_if_fail(first
!= NULL
, NULL
);
120 for (node
= first
->next
; node
; node
= node
->next
)
124 if (node
->type
!= XML_ELEMENT_NODE
)
127 /* Check names match... */
128 if (strcmp(node
->name
, first
->name
))
131 /* Check namespaces match... */
132 if ((node
->ns
== NULL
) != (first
->ns
== NULL
))
135 if (node
->ns
&& first
->ns
)
136 if (strcmp(node
->ns
->href
, first
->ns
->href
))
139 lang
= xmlNodeGetLang(node
);
143 if (strcmp(lang
, target_lang
) == 0)
154 static void xml_wrapper_finialize(GObject
*object
)
156 XMLwrapper
*xml
= (XMLwrapper
*) object
;
160 xmlFreeDoc(xml
->doc
);
164 G_OBJECT_CLASS(parent_class
)->finalize(object
);
167 static void xml_wrapper_class_init(gpointer gclass
, gpointer data
)
169 GObjectClass
*object
= (GObjectClass
*) gclass
;
171 parent_class
= g_type_class_peek_parent(gclass
);
173 object
->finalize
= xml_wrapper_finialize
;
176 static void xml_wrapper_init(GTypeInstance
*object
, gpointer gclass
)
178 XMLwrapper
*wrapper
= (XMLwrapper
*) object
;
183 static GType
xml_wrapper_get_type(void)
185 static GType type
= 0;
189 static const GTypeInfo info
=
191 sizeof (XMLwrapperClass
),
192 NULL
, /* base_init */
193 NULL
, /* base_finalise */
194 xml_wrapper_class_init
,
195 NULL
, /* class_finalise */
196 NULL
, /* class_data */
202 type
= g_type_register_static(G_TYPE_OBJECT
, "XMLwrapper",