xbel 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -5,15 +5,13 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "xbel"
8
- gem.summary = %Q{Ruby API for XBEL based on Nokogiri and Watchr.}
8
+ gem.summary = %Q{Ruby API for XBEL based on Nokogiri.}
9
9
  gem.description = %Q{}
10
10
  gem.email = "florian.assmann@email.de"
11
11
  gem.homepage = "http://xbel.monkey-patch.me"
12
12
  gem.authors = ["Florian Aßmann"]
13
- gem.add_development_dependency "shoulda", ">= 0"
14
- gem.add_dependency 'watchr', '>= 0'
13
+ gem.add_development_dependency "riot", ">= 0"
15
14
  gem.add_dependency 'nokogiri', '>= 0'
16
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
15
  end
18
16
  Jeweler::GemcutterTasks.new
19
17
  rescue LoadError
@@ -24,7 +22,7 @@ require 'rake/testtask'
24
22
  Rake::TestTask.new(:test) do |test|
25
23
  test.libs << 'lib' << 'test'
26
24
  test.pattern = 'test/**/test_*.rb'
27
- test.verbose = true
25
+ test.verbose = false
28
26
  end
29
27
 
30
28
  begin
@@ -40,8 +38,6 @@ rescue LoadError
40
38
  end
41
39
  end
42
40
 
43
- task :test => :check_dependencies
44
-
45
41
  task :default => :test
46
42
 
47
43
  require 'rake/rdoctask'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
@@ -3,26 +3,26 @@ module Nokogiri::Decorators::XBEL
3
3
  include Entry
4
4
 
5
5
  def modified
6
- if value = attribute('modified') then Date.parse value.content end
6
+ if value = self['modified'] then Date.parse value end
7
7
  end
8
8
  def modified=(value)
9
- set_attribute 'modified', value.to_s
9
+ self['modified'] = value.to_s
10
10
  end
11
11
  def visited
12
- if value = attribute('visited') then Date.parse value.content end
12
+ if value = self['visited'] then Date.parse value end
13
13
  end
14
14
  def visited=(value)
15
- set_attribute 'visited', value.to_s
15
+ self['visited'] = value.to_s
16
16
  end
17
17
  def visit
18
18
  self.visited = Date.today
19
19
  end
20
20
  def href
21
- if value = attribute('href') then value.content end
21
+ if value = self['href'] then value end
22
22
  end
23
23
  def href=(value)
24
24
  self.modified = Date.today
25
- set_attribute 'href', value
25
+ self['href'] = value
26
26
  end
27
27
  def bookmark?
28
28
  true
@@ -31,16 +31,16 @@ module Nokogiri::Decorators::XBEL
31
31
  end
32
32
 
33
33
  # Builds a bookmark with given attributes and add it.
34
- def build_bookmark(attributes = {}, &block)
34
+ def build_bookmark(title, attributes = {}, &block)
35
35
  node = Nokogiri::XML::Node.new('bookmark', document)
36
- assign_to node, attributes
36
+ assign_to node, attributes.merge('title' => title)
37
37
 
38
38
  add_child node
39
39
  end
40
40
  # Builds a folder with given attributes and add it.
41
- def build_folder(attributes = {}, &block)
41
+ def build_folder(title, attributes = {}, &block)
42
42
  node = Nokogiri::XML::Node.new('folder', document)
43
- assign_to node, attributes
43
+ assign_to node, attributes.merge('title' => title)
44
44
 
45
45
  add_child node
46
46
  end
@@ -3,21 +3,19 @@ require 'forwardable'
3
3
  require 'nokogiri'
4
4
  require 'nokogiri/decorators/xbel'
5
5
 
6
- require 'watchr'
7
-
8
6
  class XBEL < Nokogiri::XML::Document
9
7
  extend Forwardable
10
8
  def_delegators :root, :title, :title=, :desc, :desc=
11
9
 
12
- autoload :Writer, 'xbel/writer'
10
+ def self.new(major = 1, minor = 0)
11
+ parse %Q'<!DOCTYPE xbel PUBLIC "+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML" "http://www.python.org/topics/xml/dtds/xbel-1.0.dtd"><xbel version="%i.%i"></xbel>' % [major, minor]
12
+ end
13
13
 
14
14
  # Use <tt>XBEL.parse(string)</tt> create an instance.
15
15
  def initialize(*args)
16
16
  super
17
17
  decorators(Nokogiri::XML::Node) << Nokogiri::Decorators::XBEL
18
18
  decorate!
19
-
20
- # self.root = '<xbel version="1.0"></xbel>'
21
19
  end
22
20
 
23
21
  # Returns an array of version numbers.
@@ -26,13 +24,7 @@ class XBEL < Nokogiri::XML::Document
26
24
  end
27
25
  # Sets version numbers.
28
26
  def version=(*numbers)
29
- root.attribute('version').value = numbers.join '.'
30
- end
31
-
32
- # Writes XBEL to path.
33
- def write(path)
34
- # TODO: should start locking write process
35
- Writer.new(self, path).write
27
+ root.attribute('version').value = numbers * '.'
36
28
  end
37
29
 
38
30
  end
@@ -1,12 +1,6 @@
1
1
  require 'rubygems'
2
- require 'test/unit'
3
- require 'shoulda'
2
+ require 'riot'
4
3
 
5
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
5
  $LOAD_PATH.unshift(File.dirname(__FILE__))
7
6
  require 'xbel'
8
-
9
- class Test::Unit::TestCase
10
- include Nokogiri::Decorators::XBEL
11
- attr_reader :xbel
12
- end
@@ -1,35 +1,89 @@
1
1
  require 'helper'
2
2
 
3
- class TestXBEL < Test::Unit::TestCase
4
- context 'Read XBEL' do
5
- setup do
6
- @path = Pathname.new("#{ File.dirname __FILE__ }").join "complex.xbel"
7
- @xbel = XBEL.parse @path.read
8
- end
9
- should "have version [1, 0]" do
10
- assert_equal [1, 0], xbel.version
11
- end
12
- should "have title 'Some of David's Bookmarks'" do
13
- assert_equal %Q{Some of David's Bookmarks}, xbel.title
3
+ context 'New XBEL' do
4
+
5
+ asserts 'version' do
6
+ XBEL.new.version
7
+ end.equals [1, 0]
8
+ asserts 'user defined version' do
9
+ XBEL.new(2, 2).version
10
+ end.equals [2, 2]
11
+ asserts 'set version' do
12
+ xbel = XBEL.new
13
+ xbel.version = 1, 1
14
+
15
+ xbel.version
16
+ end.equals [1, 1]
17
+ should 'be empty' do
18
+ XBEL.new.root.content.empty?
19
+ end
20
+
21
+ end
22
+
23
+ context 'XBEL' do
24
+
25
+ setup do
26
+ path = File.join "#{ File.dirname __FILE__ }", 'wikipedia.xbel'
27
+ @xbel = XBEL.parse File.read(path)
28
+ end
29
+
30
+ asserts('version') { @xbel.version }.equals [1, 0]
31
+
32
+ asserts("title") { @xbel.title }.equals %q"Lesezeichen!"
33
+ should('delegate title to root') { @xbel.root.title == @xbel.title }
34
+
35
+ context 'Alias' do
36
+ setup { @alias = @xbel.root.aliases.first }
37
+ should('be an alias') { @alias.alias? }
38
+ end
39
+
40
+ context 'Folder' do
41
+ setup { @folder = @xbel.root.folders.first }
42
+
43
+ asserts('title') { @folder.title }.equals 'Wiki'
44
+ asserts('entries') { @folder.entries }.kind_of Nokogiri::XML::NodeSet
45
+ asserts('bookmarks') { @folder.bookmarks }.kind_of Nokogiri::XML::NodeSet
46
+ asserts('aliases') { @folder.bookmarks }.kind_of Nokogiri::XML::NodeSet
47
+ should('be a folder') { @folder.folder? }
48
+
49
+ context 'Bookmark' do
50
+ setup { @bookmark = @folder.bookmarks.first }
51
+
52
+ asserts('modified attribute') { @bookmark.modified }.kind_of Date
53
+ asserts('visited') { @bookmark.visited }.kind_of Date
54
+ asserts('visit') { @bookmark.visit; @bookmark.visited }.equals Date.today
55
+ should('be a bookmark') { @bookmark.bookmark? }
14
56
  end
15
- should "return all root folders" do
16
- results = xbel.root.folders
17
- results = results.map { |folder| folder.title }
18
- expect = ['HTTP Clients', 'Extensible Markup Language (XML)']
19
- assert_equal expect, results
57
+ context 'new Bookmark' do
58
+ setup do
59
+ @bookmark = @folder.build_bookmark 'Bookmark',
60
+ :href => 'http://www.github.com/boof/xbel', :description => 'desc'
61
+ end
62
+
63
+ asserts('added attribute') { @bookmark.added }.equals Date.today
64
+ asserts('title attribute') { @bookmark.title }.equals 'Bookmark'
65
+ asserts('href attribute') { @bookmark.href }.
66
+ equals 'http://www.github.com/boof/xbel'
67
+ asserts('description attribute') { @bookmark.description }.
68
+ equals 'desc'
20
69
  end
21
- should "return all bookmarks of 'HTTP Clients'" do
22
- results = xbel.root.folders.first.bookmarks
23
- results = results.map { |entry| entry.title }
24
- expect = [
25
- 'Netscape', 'Opera', 'Microsoft Internet Explorer', 'Lynx', 'Amaya'
26
- ]
27
- assert_equal expect, results
70
+
71
+ context 'new Folder' do
72
+ setup do
73
+ @subfolder = @folder.build_folder 'subfolder',
74
+ :id => 'id-2', :desc => 'description'
75
+ end
76
+ asserts('added attribute') { @subfolder.added }.equals Date.today
77
+ asserts('title attribute') { @subfolder.title }.equals 'subfolder'
78
+ asserts('id attribute') { @subfolder.id }.equals 'id-2'
79
+ asserts('desc attribute') { @subfolder.desc }.equals 'description'
28
80
  end
29
- should "return aliased bookmark" do
30
- result = xbel.root.folders.first.aliases.first.entry
31
- expect = xbel.root.folders.first.bookmarks.last
32
- assert_equal expect, result
81
+
82
+ context 'new Alias' do
83
+ setup { @alias = @folder.build_alias @folder }
84
+ should('reference its folder') { @alias.entry == @folder }
33
85
  end
86
+
34
87
  end
88
+
35
89
  end
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+ <!DOCTYPE xbel
3
+ PUBLIC "+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML"
4
+ "http://www.python.org/topics/xml/dtds/xbel-1.0.dtd">
5
+ <xbel version="1.0">
6
+ <title>Lesezeichen!</title>
7
+ <desc>Lernen von XBEL am Beispiel von zwei Lesezeichen und einer Verknüpfung</desc>
8
+ <folder id="f0" added="2007-11-10">
9
+ <title>Wiki</title>
10
+ <desc>Webseiten von Autoren-Gemeinschaften</desc>
11
+ <bookmark href="http://wikimediafoundation.org/" id="b0" added="2007-11-11" modified="2007-11-14" visited="2007-11-14">
12
+ <title>Wikimedia Foundation</title>
13
+ </bookmark>
14
+ <bookmark href="http://de.wikipedia.org/" id="b1" added="2007-11-11" modified="2007-11-14" visited="2007-12-27">
15
+ <title>Wikipedia</title>
16
+ </bookmark>
17
+ </folder>
18
+ <separator />
19
+ <alias ref="b1" />
20
+ </xbel>
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{xbel}
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Florian A\303\237mann"]
12
- s.date = %q{2009-10-28}
12
+ s.date = %q{2009-11-10}
13
13
  s.description = %q{}
14
14
  s.email = %q{florian.assmann@email.de}
15
15
  s.extra_rdoc_files = [
@@ -30,17 +30,16 @@ Gem::Specification.new do |s|
30
30
  "lib/nokogiri/decorators/xbel/folder.rb",
31
31
  "lib/nokogiri/decorators/xbel/seperator.rb",
32
32
  "lib/xbel.rb",
33
- "lib/xbel/writer.rb",
34
- "test/complex.xbel",
35
33
  "test/helper.rb",
36
34
  "test/test_xbel.rb",
35
+ "test/wikipedia.xbel",
37
36
  "xbel.gemspec"
38
37
  ]
39
38
  s.homepage = %q{http://xbel.monkey-patch.me}
40
39
  s.rdoc_options = ["--charset=UTF-8"]
41
40
  s.require_paths = ["lib"]
42
41
  s.rubygems_version = %q{1.3.5}
43
- s.summary = %q{Ruby API for XBEL based on Nokogiri and Watchr.}
42
+ s.summary = %q{Ruby API for XBEL based on Nokogiri.}
44
43
  s.test_files = [
45
44
  "test/helper.rb",
46
45
  "test/test_xbel.rb"
@@ -51,17 +50,14 @@ Gem::Specification.new do |s|
51
50
  s.specification_version = 3
52
51
 
53
52
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
54
- s.add_development_dependency(%q<shoulda>, [">= 0"])
55
- s.add_runtime_dependency(%q<watchr>, [">= 0"])
53
+ s.add_development_dependency(%q<riot>, [">= 0"])
56
54
  s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
57
55
  else
58
- s.add_dependency(%q<shoulda>, [">= 0"])
59
- s.add_dependency(%q<watchr>, [">= 0"])
56
+ s.add_dependency(%q<riot>, [">= 0"])
60
57
  s.add_dependency(%q<nokogiri>, [">= 0"])
61
58
  end
62
59
  else
63
- s.add_dependency(%q<shoulda>, [">= 0"])
64
- s.add_dependency(%q<watchr>, [">= 0"])
60
+ s.add_dependency(%q<riot>, [">= 0"])
65
61
  s.add_dependency(%q<nokogiri>, [">= 0"])
66
62
  end
67
63
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xbel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Florian A\xC3\x9Fmann"
@@ -9,11 +9,11 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-28 00:00:00 +01:00
12
+ date: 2009-11-10 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: shoulda
16
+ name: riot
17
17
  type: :development
18
18
  version_requirement:
19
19
  version_requirements: !ruby/object:Gem::Requirement
@@ -22,16 +22,6 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
- - !ruby/object:Gem::Dependency
26
- name: watchr
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
35
25
  - !ruby/object:Gem::Dependency
36
26
  name: nokogiri
37
27
  type: :runtime
@@ -65,10 +55,9 @@ files:
65
55
  - lib/nokogiri/decorators/xbel/folder.rb
66
56
  - lib/nokogiri/decorators/xbel/seperator.rb
67
57
  - lib/xbel.rb
68
- - lib/xbel/writer.rb
69
- - test/complex.xbel
70
58
  - test/helper.rb
71
59
  - test/test_xbel.rb
60
+ - test/wikipedia.xbel
72
61
  - xbel.gemspec
73
62
  has_rdoc: true
74
63
  homepage: http://xbel.monkey-patch.me
@@ -97,7 +86,7 @@ rubyforge_project:
97
86
  rubygems_version: 1.3.5
98
87
  signing_key:
99
88
  specification_version: 3
100
- summary: Ruby API for XBEL based on Nokogiri and Watchr.
89
+ summary: Ruby API for XBEL based on Nokogiri.
101
90
  test_files:
102
91
  - test/helper.rb
103
92
  - test/test_xbel.rb
@@ -1,41 +0,0 @@
1
- class XBEL::Writer #:nodoc:
2
- DOCTYPE = '<!DOCTYPE xbel PUBLIC "+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML" "http://www.python.org/topics/xml/dtds/xbel-1.0.dtd">'
3
-
4
- attr_reader :document, :lockfile_path, :path
5
- def new(document, path)
6
- @document, @path = document, path
7
- @lockfile_path = "#{ path }.lock"
8
- end
9
-
10
- def write
11
- synchronize do
12
- File.open path, 'w' do |file|
13
- file.puts DOCTYPE
14
- file << document
15
- end
16
- end
17
- end
18
-
19
- protected
20
-
21
- def locked?(path)
22
- File.exists? lockfile_path
23
- end
24
- def lock
25
- File.open(lockfile_path, 'w') { |*| yield }
26
- ensure
27
- File.unlink lockfile_path
28
- end
29
-
30
- def synchronize
31
- current_thread = Thread.current
32
-
33
- while locked?
34
- watch(lockfile_path, :delete) { |*| current_thread.run }
35
- current_thread.sleep
36
- end
37
-
38
- lock { yield }
39
- end
40
-
41
- end
@@ -1,165 +0,0 @@
1
- <?xml version="1.0"?>
2
- <!DOCTYPE xbel PUBLIC "+//IDN python.org//DTD XML Bookmark Exchange
3
- Language 1.0//EN//XML"
4
- "http://www.python.org/topics/xml/dtds/xbel-1.0.dtd">
5
- <xbel version="1.0">
6
- <title>Some of David's Bookmarks</title>
7
-
8
- <folder>
9
- <title>HTTP Clients</title>
10
-
11
- <bookmark href="http://www.netscape.com/download/" id="bookmark-1">
12
- <title>Netscape</title>
13
-
14
- <desc>Netscape 6.2 is the latest update to the Internet
15
- browsing, email and instant messagin software suite from
16
- Netscape.</desc>
17
- </bookmark>
18
-
19
- <bookmark href="http://www.opera.com/">
20
- <title>Opera</title>
21
-
22
- <desc>Opera -- Simply the Best Internet Experience</desc>
23
- </bookmark>
24
-
25
- <alias ref="bookmark-5"></alias>
26
-
27
- <bookmark href="http://www.microsoft.com/ie/">
28
- <title>Microsoft Internet Explorer</title>
29
-
30
- <desc>Internet Explorer 6 sets a new standard in privacy,
31
- reliability, and flexibility. Come see how Internet Explorer
32
- is leading the way on the Web.</desc>
33
- </bookmark>
34
-
35
- <bookmark href="http://lynx.browser.org/">
36
- <title>Lynx</title>
37
-
38
- <desc>Lynx is a fully-featured World Wide Web (WWW) client
39
- for users running cursor-addressable, character-cell display
40
- devices (e.g., vt100 terminals, vt100 emulators running on
41
- PCs or Macs, or any other character-cell display). It will
42
- display Hypertext Markup Language (HTML) documents containing
43
- links to files on the local system, as well as files on
44
- remote systems running http, gopher, ftp, wais, nntp, finger,
45
- or cso/ph/qi servers, and services accessible via logins to
46
- telnet, tn3270 or rlogin accounts. Current versions of Lynx
47
- run on Unix, VMS, Windows95/NT, 386DOS and OS/2 EMX.</desc>
48
- </bookmark>
49
-
50
- <bookmark href="http://www.w3.org/Amaya/" id="bookmark-5">
51
- <title>Amaya</title>
52
-
53
- <desc>Amaya is a browser/authoring tool that allows you to
54
- publish documents on the Web. It is used to demonstrate and
55
- test many of the new developments in Web protocols and data
56
- formats. Given the very fast moving nature of Web technology,
57
- Amaya has a central role to play. It is versatile and
58
- extensible and is available on both Unix and Windows '95/NT
59
- platforms.</desc>
60
- </bookmark>
61
-
62
- <alias ref="bookmark-1"></alias>
63
-
64
- </folder>
65
-
66
- <folder>
67
- <title>Extensible Markup Language (XML)</title>
68
-
69
- <bookmark
70
- href="http://www.sciam.com/1999/0599issue/0599bosak.html">
71
- <title>Scientific American: Feature Article: XML and the
72
- Second Generation Web: May 1999</title>
73
-
74
- <desc>The combination of hypertext and a global Internet
75
- started a revolution. A new ingredient, XML, is poised to
76
- finish the job. by Jon Bosak and Tim Bray</desc>
77
-
78
- </bookmark>
79
-
80
- <bookmark
81
- href="http://www.sciam.com/2001/0501issue/0501berners-lee.html">
82
-
83
- <title>Scientific American: Feature Article: The Semantic
84
- Web: May 2001</title>
85
-
86
- <desc>A new form of Web content that is meaningful to
87
- computers will unleash a revolution of new possibilities . by
88
- TIM BERNERS-LEE, JAMES HENDLER and ORA LASSILA</desc>
89
- </bookmark>
90
-
91
- <bookmark href="http://www.w3.org/XML/1999/XML-in-10-points">
92
-
93
- <title>XML in 10 Points</title>
94
- </bookmark>
95
-
96
- <folder>
97
- <title>Building XML Documents</title>
98
-
99
- <bookmark
100
- href="http://www.webreview.com/2000/08_04/webauthors/08_04_00_4.shtml">
101
-
102
- <title>Well-Formed XML Documents (webreview.com)</title>
103
-
104
- <desc>Still trying to tame the XML beast? Begin with this
105
- tutorial that will show you in clear terms how to build a
106
- simple XML document that is well-formed and valid.</desc>
107
- </bookmark>
108
- </folder>
109
-
110
- <folder>
111
- <title>RSS</title>
112
-
113
- <bookmark
114
- href="http://www.webreference.com/authoring/languages/xml/rss/intro/">
115
-
116
- <title>Introduction to RSS - WebReference.com</title>
117
-
118
- <desc>Rich Site Summary (RSS) is a lightweight XML format
119
- designed for sharing headlines and other Web
120
- content.</desc>
121
- </bookmark>
122
-
123
- <bookmark
124
- href="http://www.WebReview.com/1999/10_29/webauthors/10_29_99_2a.shtml">
125
-
126
- <title>WebReview.com: RSS Delivers the XML Promise</title>
127
-
128
- <desc>RSS is a content syndication format that uses the
129
- power of XML to share data over the Internet.</desc>
130
- </bookmark>
131
- </folder>
132
-
133
- <folder>
134
- <title>Extensible Stylesheet Language (XSL)</title>
135
-
136
- <bookmark
137
- href="http://www.webreview.com/2001/08_03/developers/index01.shtml">
138
-
139
- <title>WebReview.com: August 3, 2001: Introduction to
140
- XSLT</title>
141
-
142
- <desc>An introduction to XSLT</desc>
143
- </bookmark>
144
- </folder>
145
-
146
- <folder>
147
- <title>Recommended Books</title>
148
-
149
- <bookmark href="http://www.oreilly.com/catalog/learnxml/">
150
- <title>Learning XML : (Guide to) Creating Self-Describing
151
- Data</title>
152
-
153
- <desc>Eric T. Ray, (O'Reilly)</desc>
154
- </bookmark>
155
-
156
- <bookmark
157
- href="http://www.amazon.com/exec/obidos/ASIN/0789725045/">
158
- <title>XML By Example</title>
159
-
160
- <desc>Benoit Marchal</desc>
161
- </bookmark>
162
- </folder>
163
- </folder>
164
- </xbel>
165
-