4 // Copyright (C) 2005 Novell, Inc.
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
31 using System
.Collections
;
36 namespace Beagle
.Filters
38 public class FilterDocbook
: Filter
40 protected XmlTextReader reader
;
42 protected string base_path
;
43 protected string base_title
;
44 protected string base_language
;
46 protected Stack entries_stack
= new Stack ();
48 protected class DocbookEntry
{
49 public string Id
= null;
50 public string Title
= null;
51 public string Language
= null;
52 public int Depth
= -1;
53 public StringBuilder Content
= new StringBuilder ();
56 //////////////////////////////////////////////////
58 public FilterDocbook ()
63 AddSupportedFlavor (FilterFlavor
.NewFromMimeType ("application/docbook+xml"));
64 AddSupportedFlavor (FilterFlavor
.NewFromExtension (".docbook"));
66 // FIXME: Uri/Extension mapping?
67 AddSupportedFlavor (new FilterFlavor ("file:///usr/share/doc/*", ".xml", null, 0));
70 ///////////////////////////////////////////////////
72 override protected void DoOpen (FileInfo info
)
74 base_path
= info
.FullName
;
75 reader
= new XmlTextReader (Stream
);
76 reader
.XmlResolver
= null;
79 override protected void DoPullProperties ()
81 Stopwatch watch
= new Stopwatch ();
85 while (reader
.Read ()) {
86 switch (reader
.NodeType
) {
87 case XmlNodeType
.Element
:
88 if (reader
.Name
.StartsWith ("sect") || reader
.Name
.StartsWith ("chapter")) {
89 string id
= reader
.GetAttribute ("id");
91 if (id
!= null && id
!= "") {
92 DocbookEntry entry
= new DocbookEntry ();
94 entry
.Depth
= reader
.Depth
;
96 string language
= reader
.GetAttribute ("lang");
98 if (language
!= null && language
!= "")
99 entry
.Language
= language
;
101 entries_stack
.Push (entry
);
103 } else if (reader
.Name
== "article" || reader
.Name
== "book") {
104 string language
= reader
.GetAttribute ("lang");
106 if (language
!= null && language
!= "")
107 base_language
= language
;
108 } else if (reader
.Name
== "title") {
109 reader
.Read (); // Go to the text node
111 if (entries_stack
.Count
== 0 && base_title
== null) {
112 // This is probably the book title
113 base_title
= reader
.Value
;
114 } else if (entries_stack
.Count
> 0) {
115 DocbookEntry entry
= (DocbookEntry
) entries_stack
.Peek ();
117 if (entry
.Title
== null)
118 entry
.Title
= reader
.Value
;
123 case XmlNodeType
.Text
:
124 // Append text to the child indexable
125 if (entries_stack
.Count
> 0)
126 ((DocbookEntry
) entries_stack
.Peek ()).Content
.Append (reader
.Value
);
128 // Append text to the main indexable
129 AppendText (reader
.Value
);
132 case XmlNodeType
.EndElement
:
133 if (entries_stack
.Count
> 0 && ((DocbookEntry
) entries_stack
.Peek ()).Depth
== reader
.Depth
) {
134 DocbookEntry entry
, parent_entry
= null;
136 entry
= (DocbookEntry
) entries_stack
.Pop ();
138 if (entries_stack
.Count
> 0)
139 parent_entry
= (DocbookEntry
) entries_stack
.Peek ();
141 Indexable indexable
= new Indexable (UriFu
.PathToFileUri (String
.Format ("{0}#{1}", base_path
, entry
.Id
)));
142 indexable
.HitType
= "DocbookEntry";
143 indexable
.MimeType
= "text/x-docbook-entry";
144 indexable
.Filtering
= IndexableFiltering
.AlreadyFiltered
;
146 indexable
.AddProperty (Property
.NewUnsearched ("fixme:id", entry
.Id
));
148 if (entry
.Title
!= null)
149 indexable
.AddProperty (Property
.New ("dc:title", entry
.Title
));
151 // Add the docbook book title
152 if (base_title
!= null)
153 indexable
.AddProperty (Property
.NewUnsearched ("fixme:base_title", base_title
));
155 // Add the child language (or docbook language if none is specified)
156 if (entry
.Language
!= null)
157 indexable
.AddProperty (Property
.NewUnsearched ("fixme:language", entry
.Language
));
158 else if (base_language
!= null)
159 indexable
.AddProperty (Property
.NewUnsearched ("fixme:language", base_language
));
161 // Add any parent (as in docbook parent entry, not beagle) data if we have it
162 if (parent_entry
!= null) {
163 indexable
.AddProperty (Property
.NewUnsearched ("fixme:parent_id", parent_entry
.Id
));
165 if (parent_entry
.Title
!= null)
166 indexable
.AddProperty (Property
.NewUnsearched ("fixme:parent_title", parent_entry
.Title
));
170 StringReader content_reader
= new StringReader (entry
.Content
.ToString ());
171 indexable
.SetTextReader (content_reader
);
173 AddChildIndexable (indexable
);
179 // Add the common properties to the top-level
180 // file item such as Title, Language etc.
182 if (base_title
!= null)
183 AddProperty (Property
.New ("dc:title", base_title
));
185 if (base_language
!= null)
186 AddProperty (Property
.NewUnsearched ("fixme:language", base_language
));
190 // If we've successfully crawled the file but haven't
191 // found any indexables, we shouldn't consider it
192 // successfull at all (unless we have a title, which
193 // means that it's actually a docbook file, just without
195 if (ChildIndexables
.Count
== 0 && base_title
== null) {
200 Logger
.Log
.Debug ("Parsed docbook file in {0}", watch
);