|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2009 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a class to read XBEL bookmark files. |
|
8 """ |
|
9 |
|
10 from PyQt4.QtCore import * |
|
11 |
|
12 from BookmarkNode import BookmarkNode |
|
13 |
|
14 class XmlEntityResolver(QXmlStreamEntityResolver): |
|
15 """ |
|
16 Class implementing an XML entity resolver for bookmark files. |
|
17 """ |
|
18 def resolveUndeclaredEntity(self, entity): |
|
19 """ |
|
20 Public method to resolve undeclared entities. |
|
21 |
|
22 @param entity entity to be resolved (string) |
|
23 @return resolved entity (string) |
|
24 """ |
|
25 if entity == "nbsp": |
|
26 return " " |
|
27 return "" |
|
28 |
|
29 class XbelReader(QXmlStreamReader): |
|
30 """ |
|
31 Class implementing a reader object for XBEL bookmark files. |
|
32 """ |
|
33 def __init__(self): |
|
34 """ |
|
35 Constructor |
|
36 """ |
|
37 QXmlStreamReader.__init__(self) |
|
38 |
|
39 self.__resolver = XmlEntityResolver() |
|
40 self.setEntityResolver(self.__resolver) |
|
41 |
|
42 def read(self, fileNameOrDevice): |
|
43 """ |
|
44 Public method to read an XBEL bookmark file. |
|
45 |
|
46 @param fileNameOrDevice name of the file to read (string) |
|
47 or reference to the device to read (QIODevice) |
|
48 @return reference to the root node (BookmarkNode) |
|
49 """ |
|
50 if isinstance(fileNameOrDevice, QIODevice): |
|
51 self.setDevice(fileNameOrDevice) |
|
52 else: |
|
53 f = QFile(fileNameOrDevice) |
|
54 if not f.exists(): |
|
55 return BookmarkNode(BookmarkNode.Root) |
|
56 f.open(QFile.ReadOnly) |
|
57 self.setDevice(f) |
|
58 |
|
59 root = BookmarkNode(BookmarkNode.Root) |
|
60 while not self.atEnd(): |
|
61 self.readNext() |
|
62 if self.isStartElement(): |
|
63 version = self.attributes().value("version") |
|
64 if self.name() == "xbel" and \ |
|
65 (not version or version == "1.0"): |
|
66 self.__readXBEL(root) |
|
67 else: |
|
68 self.raiseError(QCoreApplication.translate( |
|
69 "XbelReader", "The file is not an XBEL version 1.0 file.")) |
|
70 |
|
71 return root |
|
72 |
|
73 def __readXBEL(self, node): |
|
74 """ |
|
75 Private method to read and parse the XBEL file. |
|
76 |
|
77 @param node reference to the node to attach to (BookmarkNode) |
|
78 """ |
|
79 if not self.isStartElement() and self.name() != "xbel": |
|
80 return |
|
81 |
|
82 while not self.atEnd(): |
|
83 self.readNext() |
|
84 if self.isEndElement(): |
|
85 break |
|
86 |
|
87 if self.isStartElement(): |
|
88 if self.name() == "folder": |
|
89 self.__readFolder(node) |
|
90 elif self.name() == "bookmark": |
|
91 self.__readBookmarkNode(node) |
|
92 elif self.name() == "separator": |
|
93 self.__readSeparator(node) |
|
94 else: |
|
95 self.__skipUnknownElement() |
|
96 |
|
97 def __readFolder(self, node): |
|
98 """ |
|
99 Private method to read and parse a folder subtree. |
|
100 |
|
101 @param node reference to the node to attach to (BookmarkNode) |
|
102 """ |
|
103 if not self.isStartElement() and self.name() != "folder": |
|
104 return |
|
105 |
|
106 folder = BookmarkNode(BookmarkNode.Folder, node) |
|
107 folder.expanded = self.attributes().value("folded") == "no" |
|
108 |
|
109 while not self.atEnd(): |
|
110 self.readNext() |
|
111 if self.isEndElement(): |
|
112 break |
|
113 |
|
114 if self.isStartElement(): |
|
115 if self.name() == "title": |
|
116 self.__readTitle(folder) |
|
117 elif self.name() == "desc": |
|
118 self.__readDescription(folder) |
|
119 elif self.name() == "folder": |
|
120 self.__readFolder(folder) |
|
121 elif self.name() == "bookmark": |
|
122 self.__readBookmarkNode(folder) |
|
123 elif self.name() == "separator": |
|
124 self.__readSeparator(folder) |
|
125 else: |
|
126 self.__skipUnknownElement() |
|
127 |
|
128 def __readTitle(self, node): |
|
129 """ |
|
130 Private method to read the title element. |
|
131 |
|
132 @param node reference to the bookmark node title belongs to (BookmarkNode) |
|
133 """ |
|
134 if not self.isStartElement() and self.name() != "title": |
|
135 return |
|
136 |
|
137 node.title = self.readElementText() |
|
138 |
|
139 def __readDescription(self, node): |
|
140 """ |
|
141 Private method to read the desc element. |
|
142 |
|
143 @param node reference to the bookmark node desc belongs to (BookmarkNode) |
|
144 """ |
|
145 if not self.isStartElement() and self.name() != "desc": |
|
146 return |
|
147 |
|
148 node.desc = self.readElementText() |
|
149 |
|
150 def __readSeparator(self, node): |
|
151 """ |
|
152 Private method to read a separator element. |
|
153 |
|
154 @param node reference to the bookmark node the separator belongs to (BookmarkNode) |
|
155 """ |
|
156 BookmarkNode(BookmarkNode.Separator, node) |
|
157 # empty elements have a start and end element |
|
158 self.readNext() |
|
159 |
|
160 def __readBookmarkNode(self, node): |
|
161 """ |
|
162 Private method to read and parse a bookmark subtree. |
|
163 |
|
164 @param node reference to the node to attach to (BookmarkNode) |
|
165 """ |
|
166 if not self.isStartElement() and self.name() != "bookmark": |
|
167 return |
|
168 |
|
169 bookmark = BookmarkNode(BookmarkNode.Bookmark, node) |
|
170 bookmark.url = self.attributes().value("href") |
|
171 |
|
172 while not self.atEnd(): |
|
173 self.readNext() |
|
174 if self.isEndElement(): |
|
175 break |
|
176 |
|
177 if self.isStartElement(): |
|
178 if self.name() == "title": |
|
179 self.__readTitle(bookmark) |
|
180 elif self.name() == "desc": |
|
181 self.__readDescription(bookmark) |
|
182 else: |
|
183 self.__skipUnknownElement() |
|
184 |
|
185 if not bookmark.title: |
|
186 bookmark.title = QCoreApplication.translate("XbelReader", "Unknown title") |
|
187 |
|
188 def __skipUnknownElement(self): |
|
189 """ |
|
190 Private method to skip over all unknown elements. |
|
191 """ |
|
192 if not self.isStartElement(): |
|
193 return |
|
194 |
|
195 while not self.atEnd(): |
|
196 self.readNext() |
|
197 if self.isEndElement(): |
|
198 break |
|
199 |
|
200 if self.isStartElement(): |
|
201 self.__skipUnknownElement() |