2 * ROX-Filer, filer for the ROX desktop project
3 * Copyright (C) 2006, Thomas Leonard and others (see changelog for details).
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place, Suite 330, Boston, MA 02111-1307 USA
20 /* xml.c - A GObject wrapper for libxml documents */
26 #include <libxml/parser.h>
33 static gpointer parent_class
= NULL
;
35 /* Static prototypes */
36 static xmlNode
*best_lang(xmlNode
*first
);
37 static void xml_wrapper_finialize(GObject
*object
);
38 static void xml_wrapper_class_init(gpointer gclass
, gpointer data
);
39 static void xml_wrapper_init(GTypeInstance
*object
, gpointer gclass
);
40 static GType
xml_wrapper_get_type(void);
42 /****************************************************************
43 * EXTERNAL INTERFACE *
44 ****************************************************************/
46 XMLwrapper
*xml_new(const char *pathname
)
53 doc
= xmlParseFile(pathname
);
55 return NULL
; /* Bad XML */
58 xml_data
= g_object_new(xml_wrapper_get_type(), NULL
);
64 /* Return the first child of the root node with this name */
65 xmlNode
*xml_get_section(XMLwrapper
*xml
, const gchar
*ns
, const gchar
*name
)
67 g_return_val_if_fail(xml
!= NULL
, NULL
);
68 g_return_val_if_fail(xml
->doc
!= NULL
, NULL
);
70 return get_subnode(xmlDocGetRootElement(xml
->doc
), ns
, name
);
73 /* Return the (first) child of this node with the given name.
75 * If there are several consecutive nodes with the same name but different
76 * xml:lang attributes, then the one matching the current locale is used,
77 * or the first one if none match.
79 xmlNode
*get_subnode(xmlNode
*node
, const char *namespaceURI
, const char *name
)
81 for (node
= node
->xmlChildrenNode
; node
; node
= node
->next
)
83 if (node
->type
!= XML_ELEMENT_NODE
)
86 if (strcmp(node
->name
, name
))
89 if (node
->ns
== NULL
|| namespaceURI
== NULL
)
91 if (node
->ns
== NULL
&& namespaceURI
== NULL
)
92 return best_lang(node
);
96 if (strcmp(node
->ns
->href
, namespaceURI
) == 0)
97 return best_lang(node
);
103 /****************************************************************
104 * INTERNAL FUNCTIONS *
105 ****************************************************************/
107 /* Taking this node and each directly following node with the same name,
108 * return the one which matches the current LANG.
109 * Return the node itself if nothing matches.
111 static xmlNode
*best_lang(xmlNode
*first
)
113 xmlNode
*node
= first
;
114 xmlNode
*fallback
= NULL
;
115 const char *target_lang
= current_lang
? current_lang
: "en";
118 g_return_val_if_fail(first
!= NULL
, NULL
);
120 territory
= strchr(target_lang
, '_');
122 for (node
= first
->next
; node
; node
= node
->next
)
126 if (node
->type
!= XML_ELEMENT_NODE
)
129 /* Check names match... */
130 if (strcmp(node
->name
, first
->name
))
133 /* Check namespaces match... */
134 if ((node
->ns
== NULL
) != (first
->ns
== NULL
))
137 if (node
->ns
&& first
->ns
)
138 if (strcmp(node
->ns
->href
, first
->ns
->href
))
141 lang
= xmlNodeGetLang(node
);
145 if (strcmp(lang
, target_lang
) == 0)
150 if (territory
&& strlen(lang
) == (territory
- target_lang
) &&
151 strncmp(lang
, target_lang
, territory
- target_lang
) == 0)
158 return fallback
? fallback
: first
;
161 static void xml_wrapper_finialize(GObject
*object
)
163 XMLwrapper
*xml
= (XMLwrapper
*) object
;
167 xmlFreeDoc(xml
->doc
);
171 G_OBJECT_CLASS(parent_class
)->finalize(object
);
174 static void xml_wrapper_class_init(gpointer gclass
, gpointer data
)
176 GObjectClass
*object
= (GObjectClass
*) gclass
;
178 parent_class
= g_type_class_peek_parent(gclass
);
180 object
->finalize
= xml_wrapper_finialize
;
183 static void xml_wrapper_init(GTypeInstance
*object
, gpointer gclass
)
185 XMLwrapper
*wrapper
= (XMLwrapper
*) object
;
190 static GType
xml_wrapper_get_type(void)
192 static GType type
= 0;
196 static const GTypeInfo info
=
198 sizeof (XMLwrapperClass
),
199 NULL
, /* base_init */
200 NULL
, /* base_finalise */
201 xml_wrapper_class_init
,
202 NULL
, /* class_finalise */
203 NULL
, /* class_data */
209 type
= g_type_register_static(G_TYPE_OBJECT
, "XMLwrapper",