docbook 0.1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/CLAUDE.md +19 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/README.adoc +335 -0
- data/Rakefile +12 -0
- data/docs/.lycheeignore +33 -0
- data/docs/Gemfile +10 -0
- data/docs/INDEX.adoc +67 -0
- data/docs/_config.yml +186 -0
- data/docs/advanced/element-classes.adoc +185 -0
- data/docs/advanced/frontend-customization.adoc +193 -0
- data/docs/advanced/index.adoc +14 -0
- data/docs/advanced/templates.adoc +123 -0
- data/docs/features/element-coverage.adoc +373 -0
- data/docs/features/html-output/data-model.adoc +285 -0
- data/docs/features/html-output/directory-mode.adoc +180 -0
- data/docs/features/html-output/index.adoc +90 -0
- data/docs/features/html-output/single-file-mode.adoc +125 -0
- data/docs/features/index-generation.adoc +197 -0
- data/docs/features/index.adoc +63 -0
- data/docs/features/numbering.adoc +183 -0
- data/docs/features/toc-generation.adoc +150 -0
- data/docs/features/xinclude/fragid-schemes.adoc +287 -0
- data/docs/features/xinclude/index.adoc +119 -0
- data/docs/features/xinclude/text-includes.adoc +123 -0
- data/docs/features/xinclude/xml-includes.adoc +167 -0
- data/docs/getting-started/index.adoc +50 -0
- data/docs/getting-started/installation.adoc +113 -0
- data/docs/getting-started/quick-start.adoc +161 -0
- data/docs/guides/converting-article.adoc +188 -0
- data/docs/guides/converting-book.adoc +192 -0
- data/docs/guides/index.adoc +12 -0
- data/docs/guides/roundtrip-testing.adoc +129 -0
- data/docs/interfaces/cli/format-command.adoc +109 -0
- data/docs/interfaces/cli/index.adoc +73 -0
- data/docs/interfaces/cli/roundtrip-command.adoc +125 -0
- data/docs/interfaces/cli/to-html-command.adoc +178 -0
- data/docs/interfaces/cli/validate-command.adoc +104 -0
- data/docs/interfaces/index.adoc +101 -0
- data/docs/interfaces/ruby-api/html-output.adoc +186 -0
- data/docs/interfaces/ruby-api/index.adoc +111 -0
- data/docs/interfaces/ruby-api/parsing.adoc +202 -0
- data/docs/interfaces/ruby-api/xinclude.adoc +162 -0
- data/docs/interfaces/ruby-api/xref-resolution.adoc +156 -0
- data/docs/lychee.toml +42 -0
- data/docs/reference/cli-options.adoc +155 -0
- data/docs/reference/content-block-types.adoc +243 -0
- data/docs/reference/glossary.adoc +119 -0
- data/docs/reference/index.adoc +12 -0
- data/docs/reference/supported-elements.adoc +749 -0
- data/docs/understanding/architecture.adoc +145 -0
- data/docs/understanding/content-pipeline.adoc +102 -0
- data/docs/understanding/data-models.adoc +156 -0
- data/docs/understanding/index.adoc +34 -0
- data/exe/docbook +7 -0
- data/frontend/dist/app.css +1 -0
- data/frontend/dist/app.iife.js +24 -0
- data/frontend/package-lock.json +1445 -0
- data/frontend/package.json +22 -0
- data/frontend/src/App.vue +230 -0
- data/frontend/src/app.ts +8 -0
- data/frontend/src/components/AppSidebar.vue +116 -0
- data/frontend/src/components/AppendixSection.vue +39 -0
- data/frontend/src/components/BlockRenderer.vue +358 -0
- data/frontend/src/components/ChapterSection.vue +32 -0
- data/frontend/src/components/ContentRenderer.vue +13 -0
- data/frontend/src/components/EbookContainer.vue +147 -0
- data/frontend/src/components/EbookTopBar.vue +116 -0
- data/frontend/src/components/PartSection.vue +44 -0
- data/frontend/src/components/ReferenceEntry.vue +80 -0
- data/frontend/src/components/SearchModal.vue +286 -0
- data/frontend/src/components/SectionContent.vue +31 -0
- data/frontend/src/components/SettingsPanel.vue +236 -0
- data/frontend/src/components/TocTreeItem.vue +135 -0
- data/frontend/src/composables/useEbookStore.ts +191 -0
- data/frontend/src/composables/useSearch.ts +249 -0
- data/frontend/src/env.d.ts +7 -0
- data/frontend/src/stores/documentStore.ts +221 -0
- data/frontend/src/stores/uiStore.ts +98 -0
- data/frontend/src/styles.css +253 -0
- data/frontend/tsconfig.json +24 -0
- data/frontend/tsconfig.node.json +11 -0
- data/frontend/vite.config.ts +30 -0
- data/lib/docbook/cli.rb +123 -0
- data/lib/docbook/document.rb +67 -0
- data/lib/docbook/elements/abbrev.rb +16 -0
- data/lib/docbook/elements/acknowledgements.rb +22 -0
- data/lib/docbook/elements/address.rb +18 -0
- data/lib/docbook/elements/alt.rb +16 -0
- data/lib/docbook/elements/annotation.rb +18 -0
- data/lib/docbook/elements/appendix.rb +34 -0
- data/lib/docbook/elements/article.rb +31 -0
- data/lib/docbook/elements/att.rb +15 -0
- data/lib/docbook/elements/attribution.rb +20 -0
- data/lib/docbook/elements/audioobject.rb +18 -0
- data/lib/docbook/elements/author.rb +18 -0
- data/lib/docbook/elements/bibliography.rb +24 -0
- data/lib/docbook/elements/bibliomixed.rb +40 -0
- data/lib/docbook/elements/biblioref.rb +20 -0
- data/lib/docbook/elements/blockquote.rb +26 -0
- data/lib/docbook/elements/book.rb +36 -0
- data/lib/docbook/elements/buildtarget.rb +16 -0
- data/lib/docbook/elements/callout.rb +22 -0
- data/lib/docbook/elements/calloutlist.rb +22 -0
- data/lib/docbook/elements/caution.rb +30 -0
- data/lib/docbook/elements/chapter.rb +62 -0
- data/lib/docbook/elements/citation.rb +16 -0
- data/lib/docbook/elements/citerefentry.rb +26 -0
- data/lib/docbook/elements/citetitle.rb +20 -0
- data/lib/docbook/elements/classname.rb +16 -0
- data/lib/docbook/elements/code.rb +16 -0
- data/lib/docbook/elements/colophon.rb +22 -0
- data/lib/docbook/elements/computeroutput.rb +18 -0
- data/lib/docbook/elements/copyright.rb +17 -0
- data/lib/docbook/elements/danger.rb +28 -0
- data/lib/docbook/elements/date.rb +16 -0
- data/lib/docbook/elements/dedication.rb +22 -0
- data/lib/docbook/elements/dir.rb +16 -0
- data/lib/docbook/elements/emphasis.rb +18 -0
- data/lib/docbook/elements/entry.rb +30 -0
- data/lib/docbook/elements/entrytbl.rb +22 -0
- data/lib/docbook/elements/equation.rb +26 -0
- data/lib/docbook/elements/example.rb +30 -0
- data/lib/docbook/elements/fieldsynopsis.rb +21 -0
- data/lib/docbook/elements/figure.rb +28 -0
- data/lib/docbook/elements/filename.rb +16 -0
- data/lib/docbook/elements/firstname.rb +16 -0
- data/lib/docbook/elements/firstterm.rb +18 -0
- data/lib/docbook/elements/footnote.rb +22 -0
- data/lib/docbook/elements/footnoteref.rb +21 -0
- data/lib/docbook/elements/foreignphrase.rb +18 -0
- data/lib/docbook/elements/formalpara.rb +20 -0
- data/lib/docbook/elements/function.rb +16 -0
- data/lib/docbook/elements/glossary.rb +24 -0
- data/lib/docbook/elements/glossdef.rb +18 -0
- data/lib/docbook/elements/glossentry.rb +26 -0
- data/lib/docbook/elements/glosssee.rb +18 -0
- data/lib/docbook/elements/glossseealso.rb +18 -0
- data/lib/docbook/elements/glossterm.rb +18 -0
- data/lib/docbook/elements/holder.rb +16 -0
- data/lib/docbook/elements/honorific.rb +16 -0
- data/lib/docbook/elements/imagedata.rb +29 -0
- data/lib/docbook/elements/imageobject.rb +22 -0
- data/lib/docbook/elements/important.rb +30 -0
- data/lib/docbook/elements/index.rb +26 -0
- data/lib/docbook/elements/indexdiv.rb +22 -0
- data/lib/docbook/elements/indexentry.rb +22 -0
- data/lib/docbook/elements/indexterm.rb +34 -0
- data/lib/docbook/elements/info.rb +25 -0
- data/lib/docbook/elements/informalexample.rb +24 -0
- data/lib/docbook/elements/informalfigure.rb +20 -0
- data/lib/docbook/elements/inlinemediaobject.rb +22 -0
- data/lib/docbook/elements/itemizedlist.rb +21 -0
- data/lib/docbook/elements/legalnotice.rb +22 -0
- data/lib/docbook/elements/link.rb +26 -0
- data/lib/docbook/elements/listitem.rb +32 -0
- data/lib/docbook/elements/literal.rb +16 -0
- data/lib/docbook/elements/literallayout.rb +22 -0
- data/lib/docbook/elements/mediaobject.rb +26 -0
- data/lib/docbook/elements/msg.rb +20 -0
- data/lib/docbook/elements/msgexplan.rb +22 -0
- data/lib/docbook/elements/msgset.rb +22 -0
- data/lib/docbook/elements/note.rb +30 -0
- data/lib/docbook/elements/orderedlist.rb +23 -0
- data/lib/docbook/elements/orgname.rb +16 -0
- data/lib/docbook/elements/para.rb +61 -0
- data/lib/docbook/elements/paragraph_like.rb +18 -0
- data/lib/docbook/elements/parameter.rb +16 -0
- data/lib/docbook/elements/part.rb +38 -0
- data/lib/docbook/elements/personname.rb +22 -0
- data/lib/docbook/elements/phrase.rb +20 -0
- data/lib/docbook/elements/preface.rb +58 -0
- data/lib/docbook/elements/primary.rb +16 -0
- data/lib/docbook/elements/procedure.rb +24 -0
- data/lib/docbook/elements/productname.rb +18 -0
- data/lib/docbook/elements/productnumber.rb +16 -0
- data/lib/docbook/elements/programlisting.rb +28 -0
- data/lib/docbook/elements/property.rb +16 -0
- data/lib/docbook/elements/pubdate.rb +16 -0
- data/lib/docbook/elements/publishername.rb +16 -0
- data/lib/docbook/elements/quotation.rb +24 -0
- data/lib/docbook/elements/quote.rb +18 -0
- data/lib/docbook/elements/refentry.rb +32 -0
- data/lib/docbook/elements/refentrytitle.rb +16 -0
- data/lib/docbook/elements/reference.rb +26 -0
- data/lib/docbook/elements/refmeta.rb +29 -0
- data/lib/docbook/elements/refmiscinfo.rb +16 -0
- data/lib/docbook/elements/refname.rb +16 -0
- data/lib/docbook/elements/refnamediv.rb +22 -0
- data/lib/docbook/elements/refpurpose.rb +16 -0
- data/lib/docbook/elements/refsect1.rb +22 -0
- data/lib/docbook/elements/refsect2.rb +22 -0
- data/lib/docbook/elements/refsect3.rb +22 -0
- data/lib/docbook/elements/refsection.rb +32 -0
- data/lib/docbook/elements/releaseinfo.rb +16 -0
- data/lib/docbook/elements/remark.rb +20 -0
- data/lib/docbook/elements/replaceable.rb +16 -0
- data/lib/docbook/elements/row.rb +15 -0
- data/lib/docbook/elements/screen.rb +28 -0
- data/lib/docbook/elements/secondary.rb +16 -0
- data/lib/docbook/elements/sect1.rb +26 -0
- data/lib/docbook/elements/sect2.rb +24 -0
- data/lib/docbook/elements/sect3.rb +24 -0
- data/lib/docbook/elements/sect4.rb +24 -0
- data/lib/docbook/elements/sect5.rb +22 -0
- data/lib/docbook/elements/section.rb +66 -0
- data/lib/docbook/elements/see.rb +16 -0
- data/lib/docbook/elements/seealso.rb +18 -0
- data/lib/docbook/elements/set.rb +26 -0
- data/lib/docbook/elements/setindex.rb +24 -0
- data/lib/docbook/elements/sidebar.rb +22 -0
- data/lib/docbook/elements/simplesect.rb +32 -0
- data/lib/docbook/elements/step.rb +26 -0
- data/lib/docbook/elements/substeps.rb +18 -0
- data/lib/docbook/elements/subtitle.rb +16 -0
- data/lib/docbook/elements/surname.rb +16 -0
- data/lib/docbook/elements/table.rb +24 -0
- data/lib/docbook/elements/tag.rb +20 -0
- data/lib/docbook/elements/tbody.rb +15 -0
- data/lib/docbook/elements/term.rb +37 -0
- data/lib/docbook/elements/tertiary.rb +16 -0
- data/lib/docbook/elements/textobject.rb +18 -0
- data/lib/docbook/elements/tfoot.rb +15 -0
- data/lib/docbook/elements/tgroup.rb +21 -0
- data/lib/docbook/elements/thead.rb +15 -0
- data/lib/docbook/elements/tip.rb +30 -0
- data/lib/docbook/elements/title.rb +16 -0
- data/lib/docbook/elements/toc.rb +24 -0
- data/lib/docbook/elements/tocdiv.rb +22 -0
- data/lib/docbook/elements/tocentry.rb +20 -0
- data/lib/docbook/elements/topic.rb +26 -0
- data/lib/docbook/elements/type.rb +16 -0
- data/lib/docbook/elements/uri.rb +16 -0
- data/lib/docbook/elements/userinput.rb +18 -0
- data/lib/docbook/elements/variable.rb +16 -0
- data/lib/docbook/elements/variablelist.rb +19 -0
- data/lib/docbook/elements/varlistentry.rb +17 -0
- data/lib/docbook/elements/version.rb +16 -0
- data/lib/docbook/elements/videoobject.rb +18 -0
- data/lib/docbook/elements/warning.rb +30 -0
- data/lib/docbook/elements/xref.rb +18 -0
- data/lib/docbook/elements/year.rb +16 -0
- data/lib/docbook/elements.rb +204 -0
- data/lib/docbook/models/document_metadata.rb +30 -0
- data/lib/docbook/models/document_root.rb +33 -0
- data/lib/docbook/models/index_entry.rb +28 -0
- data/lib/docbook/models/reading_position.rb +22 -0
- data/lib/docbook/models/section_number.rb +18 -0
- data/lib/docbook/models/section_root.rb +29 -0
- data/lib/docbook/models/toc_node.rb +24 -0
- data/lib/docbook/models.rb +16 -0
- data/lib/docbook/output/data.rb +196 -0
- data/lib/docbook/output/html.rb +1450 -0
- data/lib/docbook/output/index_generator.rb +281 -0
- data/lib/docbook/output.rb +8 -0
- data/lib/docbook/services/document_builder.rb +258 -0
- data/lib/docbook/services/element_to_hash.rb +287 -0
- data/lib/docbook/services/index_generator.rb +134 -0
- data/lib/docbook/services/numbering_service.rb +186 -0
- data/lib/docbook/services/toc_generator.rb +138 -0
- data/lib/docbook/services.rb +14 -0
- data/lib/docbook/templates/document.html.liquid +20 -0
- data/lib/docbook/templates/partials/_head.liquid +39 -0
- data/lib/docbook/templates/partials/_scripts.liquid +10 -0
- data/lib/docbook/version.rb +5 -0
- data/lib/docbook/xinclude_resolver.rb +217 -0
- data/lib/docbook/xref_resolver.rb +78 -0
- data/lib/docbook.rb +17 -0
- data/sig/docbook.rbs +4 -0
- metadata +385 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Quick Start
|
|
4
|
+
parent: Getting Started
|
|
5
|
+
nav_order: 2
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
== Quick Start
|
|
9
|
+
|
|
10
|
+
This page walks you through the three most common operations using the `docbook` command-line tool: validating, converting to HTML, and formatting DocBook XML files.
|
|
11
|
+
|
|
12
|
+
=== Prerequisites
|
|
13
|
+
|
|
14
|
+
Make sure the gem is installed and the `docbook` command is available. See <<installation>> for details.
|
|
15
|
+
|
|
16
|
+
For these examples, we will use a sample DocBook 5 article file called `article.xml`:
|
|
17
|
+
|
|
18
|
+
[source,xml]
|
|
19
|
+
----
|
|
20
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
21
|
+
<article xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="my-article">
|
|
22
|
+
<info>
|
|
23
|
+
<title>Getting Started with DocBook</title>
|
|
24
|
+
</info>
|
|
25
|
+
<section xml:id="intro">
|
|
26
|
+
<title>Introduction</title>
|
|
27
|
+
<para>This is a sample DocBook article demonstrating the basic features
|
|
28
|
+
of the Metanorma DocBook gem.</para>
|
|
29
|
+
</section>
|
|
30
|
+
<section xml:id="usage">
|
|
31
|
+
<title>Usage</title>
|
|
32
|
+
<para>See the <xref linkend="intro"/> for background information.</para>
|
|
33
|
+
</section>
|
|
34
|
+
</article>
|
|
35
|
+
----
|
|
36
|
+
|
|
37
|
+
=== 1. Validate a DocBook File
|
|
38
|
+
|
|
39
|
+
The `validate` command checks whether an XML file is well-formed:
|
|
40
|
+
|
|
41
|
+
[source,bash]
|
|
42
|
+
----
|
|
43
|
+
$ docbook validate article.xml
|
|
44
|
+
article.xml: valid
|
|
45
|
+
----
|
|
46
|
+
|
|
47
|
+
If the file contains errors, the command prints each error to stderr and exits with code 1:
|
|
48
|
+
|
|
49
|
+
[source,bash]
|
|
50
|
+
----
|
|
51
|
+
$ docbook validate broken.xml
|
|
52
|
+
broken.xml: 6:14: FATAL: Opening and ending tag mismatch: section line 4 and artcle
|
|
53
|
+
broken.xml: 1 file, 1 failures
|
|
54
|
+
$ echo $?
|
|
55
|
+
1
|
|
56
|
+
----
|
|
57
|
+
|
|
58
|
+
*TIP:* The `validate` command checks XML well-formedness using Nokogiri. It does not validate against the DocBook schema (DTD or RelaxNG).
|
|
59
|
+
|
|
60
|
+
=== 2. Convert to HTML
|
|
61
|
+
|
|
62
|
+
The `to-html` command converts a DocBook XML file to a self-contained HTML document.
|
|
63
|
+
|
|
64
|
+
==== Single-File Mode (default)
|
|
65
|
+
|
|
66
|
+
[source,bash]
|
|
67
|
+
----
|
|
68
|
+
$ docbook to-html article.xml -o output.html
|
|
69
|
+
Written to output.html
|
|
70
|
+
----
|
|
71
|
+
|
|
72
|
+
This produces a single HTML file with all assets (CSS, JavaScript, images) embedded inline. Images are converted to Base64 data URIs, making the file completely self-contained and portable.
|
|
73
|
+
|
|
74
|
+
To write to stdout instead of a file, omit the `--output` option:
|
|
75
|
+
|
|
76
|
+
[source,bash]
|
|
77
|
+
----
|
|
78
|
+
$ docbook to-html article.xml
|
|
79
|
+
<!DOCTYPE html><html>...
|
|
80
|
+
----
|
|
81
|
+
|
|
82
|
+
==== Directory Mode
|
|
83
|
+
|
|
84
|
+
Use `--output-type directory` to generate a multi-file output suitable for web serving:
|
|
85
|
+
|
|
86
|
+
[source,bash]
|
|
87
|
+
----
|
|
88
|
+
$ docbook to-html article.xml -o my-book --output-type directory
|
|
89
|
+
Written to my-book/index.html and assets/
|
|
90
|
+
----
|
|
91
|
+
|
|
92
|
+
Directory mode creates the following structure:
|
|
93
|
+
|
|
94
|
+
[source]
|
|
95
|
+
----
|
|
96
|
+
my-book/
|
|
97
|
+
index.html # HTML shell with Vue.js app
|
|
98
|
+
docbook.data.json # Structured content data (TOC, sections, index)
|
|
99
|
+
assets/
|
|
100
|
+
app.css # Stylesheet
|
|
101
|
+
app.iife.js # Vue.js application bundle
|
|
102
|
+
----
|
|
103
|
+
|
|
104
|
+
==== XInclude Resolution
|
|
105
|
+
|
|
106
|
+
By default, XIncludes are resolved before conversion. To disable this:
|
|
107
|
+
|
|
108
|
+
[source,bash]
|
|
109
|
+
----
|
|
110
|
+
$ docbook to-html book.xml -o output.html --no-xinclude
|
|
111
|
+
----
|
|
112
|
+
|
|
113
|
+
=== 3. Format (Prettify) DocBook XML
|
|
114
|
+
|
|
115
|
+
The `format` command reformats a DocBook XML file with consistent indentation:
|
|
116
|
+
|
|
117
|
+
[source,bash]
|
|
118
|
+
----
|
|
119
|
+
$ docbook format article.xml -o formatted.xml
|
|
120
|
+
Written to formatted.xml
|
|
121
|
+
----
|
|
122
|
+
|
|
123
|
+
The output is a properly indented XML document with an XML declaration:
|
|
124
|
+
|
|
125
|
+
[source,xml]
|
|
126
|
+
----
|
|
127
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
128
|
+
<article xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="my-article">
|
|
129
|
+
<info>
|
|
130
|
+
<title>Getting Started with DocBook</title>
|
|
131
|
+
</info>
|
|
132
|
+
<section xml:id="intro">
|
|
133
|
+
<title>Introduction</title>
|
|
134
|
+
<para>This is a sample DocBook article demonstrating the basic features
|
|
135
|
+
of the Metanorma DocBook gem.</para>
|
|
136
|
+
</section>
|
|
137
|
+
</article>
|
|
138
|
+
----
|
|
139
|
+
|
|
140
|
+
To print to stdout, omit the `--output` option:
|
|
141
|
+
|
|
142
|
+
[source,bash]
|
|
143
|
+
----
|
|
144
|
+
$ docbook format article.xml
|
|
145
|
+
----
|
|
146
|
+
|
|
147
|
+
To resolve XIncludes before formatting:
|
|
148
|
+
|
|
149
|
+
[source,bash]
|
|
150
|
+
----
|
|
151
|
+
$ docbook format book.xml --xinclude -o book-flat.xml
|
|
152
|
+
Written to book-flat.xml
|
|
153
|
+
----
|
|
154
|
+
|
|
155
|
+
=== Next Steps
|
|
156
|
+
|
|
157
|
+
Now that you can validate, convert, and format DocBook files, explore the full documentation:
|
|
158
|
+
|
|
159
|
+
* *<<interfaces,Interfaces>>* -- Detailed CLI reference and Ruby API documentation
|
|
160
|
+
* *<<../interfaces/cli/,CLI Reference>>* -- All commands, options, and examples
|
|
161
|
+
* *<<../interfaces/ruby-api/,Ruby API>>* -- Programmatic access to parsing, XInclude resolution, cross-references, and HTML output
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Converting an Article
|
|
4
|
+
parent: Guides
|
|
5
|
+
nav_order: 2
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Converting an Article
|
|
9
|
+
|
|
10
|
+
Articles are simpler than books -- they have a flat structure with no
|
|
11
|
+
parts, chapters, or appendices. This guide shows how to convert a
|
|
12
|
+
DocBook article to HTML.
|
|
13
|
+
|
|
14
|
+
== Article structure
|
|
15
|
+
|
|
16
|
+
A DocBook article uses `<section>` elements for its hierarchy instead
|
|
17
|
+
of the part/chapter structure of a book. Here is a complete example:
|
|
18
|
+
|
|
19
|
+
[source,xml]
|
|
20
|
+
----
|
|
21
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
22
|
+
<article xmlns="http://docbook.org/ns/docbook" version="5.0"
|
|
23
|
+
xml:id="api-design">
|
|
24
|
+
<info>
|
|
25
|
+
<title>API Design Principles</title>
|
|
26
|
+
<author>
|
|
27
|
+
<personname>
|
|
28
|
+
<firstname>Alex</firstname>
|
|
29
|
+
<surname>Architect</surname>
|
|
30
|
+
</personname>
|
|
31
|
+
</author>
|
|
32
|
+
<pubdate>2025-01-15</pubdate>
|
|
33
|
+
</info>
|
|
34
|
+
|
|
35
|
+
<section xml:id="s-overview">
|
|
36
|
+
<title>Overview</title>
|
|
37
|
+
<para>This article presents key principles for designing
|
|
38
|
+
robust and maintainable APIs.</para>
|
|
39
|
+
|
|
40
|
+
<section xml:id="s-overview-goals">
|
|
41
|
+
<title>Design Goals</title>
|
|
42
|
+
<para>An API should be consistent, discoverable, and
|
|
43
|
+
resilient to change.</para>
|
|
44
|
+
</section>
|
|
45
|
+
</section>
|
|
46
|
+
|
|
47
|
+
<section xml:id="s-patterns">
|
|
48
|
+
<title>Common Patterns</title>
|
|
49
|
+
|
|
50
|
+
<para>REST APIs typically follow these patterns:</para>
|
|
51
|
+
|
|
52
|
+
<itemizedlist>
|
|
53
|
+
<listitem>
|
|
54
|
+
<para>Use nouns for resource endpoints.</para>
|
|
55
|
+
</listitem>
|
|
56
|
+
<listitem>
|
|
57
|
+
<para>Return appropriate HTTP status codes.</para>
|
|
58
|
+
</listitem>
|
|
59
|
+
<listitem>
|
|
60
|
+
<para>Version your API from the start.</para>
|
|
61
|
+
</listitem>
|
|
62
|
+
</itemizedlist>
|
|
63
|
+
|
|
64
|
+
<example>
|
|
65
|
+
<title>Sample endpoint</title>
|
|
66
|
+
<programlisting language="bash">
|
|
67
|
+
curl -X GET https://api.example.com/v1/users \
|
|
68
|
+
-H "Authorization: Bearer TOKEN"
|
|
69
|
+
</programlisting>
|
|
70
|
+
</example>
|
|
71
|
+
</section>
|
|
72
|
+
|
|
73
|
+
<section xml:id="s-error-handling">
|
|
74
|
+
<title>Error Handling</title>
|
|
75
|
+
|
|
76
|
+
<para>Always provide structured error responses:</para>
|
|
77
|
+
|
|
78
|
+
<programlisting language="json">
|
|
79
|
+
{
|
|
80
|
+
"error": {
|
|
81
|
+
"code": "VALIDATION_ERROR",
|
|
82
|
+
"message": "The 'email' field is required."
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
</programlisting>
|
|
86
|
+
|
|
87
|
+
<note>
|
|
88
|
+
<title>Important</title>
|
|
89
|
+
<para>Never expose internal stack traces in production
|
|
90
|
+
error responses.</para>
|
|
91
|
+
</note>
|
|
92
|
+
|
|
93
|
+
<warning>
|
|
94
|
+
<para>Returning HTML error pages from a JSON API endpoint
|
|
95
|
+
breaks client parsing.</para>
|
|
96
|
+
</warning>
|
|
97
|
+
</section>
|
|
98
|
+
|
|
99
|
+
<section xml:id="s-figure-example">
|
|
100
|
+
<title>Architecture Diagram</title>
|
|
101
|
+
<figure>
|
|
102
|
+
<title>System Architecture</title>
|
|
103
|
+
<mediaobject>
|
|
104
|
+
<imageobject>
|
|
105
|
+
<imagedata fileref="images/architecture.png"/>
|
|
106
|
+
</imageobject>
|
|
107
|
+
</mediaobject>
|
|
108
|
+
</figure>
|
|
109
|
+
</section>
|
|
110
|
+
</article>
|
|
111
|
+
----
|
|
112
|
+
|
|
113
|
+
== CLI conversion
|
|
114
|
+
|
|
115
|
+
To convert the article to a single HTML file:
|
|
116
|
+
|
|
117
|
+
....
|
|
118
|
+
docbook to-html article.xml -o article.html
|
|
119
|
+
....
|
|
120
|
+
|
|
121
|
+
For directory output:
|
|
122
|
+
|
|
123
|
+
....
|
|
124
|
+
docbook to-html article.xml -o article-out --output-type directory
|
|
125
|
+
....
|
|
126
|
+
|
|
127
|
+
Note that XInclude resolution is enabled by default for `to-html`. If
|
|
128
|
+
your article does not use XIncludes, this has no effect.
|
|
129
|
+
|
|
130
|
+
== Ruby API conversion
|
|
131
|
+
|
|
132
|
+
[source,ruby]
|
|
133
|
+
----
|
|
134
|
+
require "docbook"
|
|
135
|
+
|
|
136
|
+
xml = File.read("article.xml")
|
|
137
|
+
|
|
138
|
+
# Parse the article
|
|
139
|
+
doc = Docbook::Document.from_xml(xml)
|
|
140
|
+
|
|
141
|
+
# Resolve cross-references
|
|
142
|
+
xref = Docbook::XrefResolver.new(doc).resolve!
|
|
143
|
+
|
|
144
|
+
# Generate HTML (single file)
|
|
145
|
+
html = Docbook::Output::Html.new(
|
|
146
|
+
doc,
|
|
147
|
+
xref_resolver: xref,
|
|
148
|
+
output_mode: :single_file,
|
|
149
|
+
base_path: File.dirname(File.expand_path("article.xml"))
|
|
150
|
+
).to_html
|
|
151
|
+
|
|
152
|
+
File.write("article.html", html)
|
|
153
|
+
----
|
|
154
|
+
|
|
155
|
+
== What to expect in the output
|
|
156
|
+
|
|
157
|
+
The article conversion produces the following:
|
|
158
|
+
|
|
159
|
+
* **Title** -- The article title from `<info><title>` appears in the
|
|
160
|
+
browser tab and as the document header.
|
|
161
|
+
* **Section tree** -- Each `<section>` becomes a navigable entry in the
|
|
162
|
+
TOC sidebar. Nested sections appear as children.
|
|
163
|
+
* **Numbering** -- Sections receive hierarchical numbers (1, 1.1, 2,
|
|
164
|
+
2.1, etc.).
|
|
165
|
+
* **Code blocks** -- `<programlisting>` elements are rendered with
|
|
166
|
+
Prism.js syntax highlighting. The `language` attribute determines the
|
|
167
|
+
highlighting language.
|
|
168
|
+
* **Lists** -- `<itemizedlist>` renders as a bulleted list,
|
|
169
|
+
`<orderedlist>` as a numbered list.
|
|
170
|
+
* **Admonitions** -- `<note>`, `<warning>`, `<caution>`, `<important>`,
|
|
171
|
+
and `<tip>` render as styled callout boxes.
|
|
172
|
+
* **Figures** -- `<figure>` with `<mediaobject>` renders the image with
|
|
173
|
+
an optional caption.
|
|
174
|
+
* **Examples** -- `<example>` renders with its title and content.
|
|
175
|
+
|
|
176
|
+
== Inline content
|
|
177
|
+
|
|
178
|
+
Articles support the same inline elements as books. The following
|
|
179
|
+
elements are rendered correctly inside `<para>` and other block
|
|
180
|
+
elements:
|
|
181
|
+
|
|
182
|
+
* `<emphasis>` -- Italic or bold (based on `role` attribute)
|
|
183
|
+
* `<code>` and `<literal>` -- Monospace inline code
|
|
184
|
+
* `<link xlink:href="...">` -- Hyperlinks
|
|
185
|
+
* `<xref linkend="...">` -- Cross-references to other sections
|
|
186
|
+
* `<filename>` -- File names in monospace
|
|
187
|
+
* `<quote>` -- Quoted text
|
|
188
|
+
* `<citetitle>` -- Citation titles
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Converting a Book
|
|
4
|
+
parent: Guides
|
|
5
|
+
nav_order: 1
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Converting a Book
|
|
9
|
+
|
|
10
|
+
This guide walks through converting a complete DocBook 5 book document
|
|
11
|
+
to HTML using the Metanorma DocBook gem.
|
|
12
|
+
|
|
13
|
+
== Sample book structure
|
|
14
|
+
|
|
15
|
+
A typical DocBook book has the following structure:
|
|
16
|
+
|
|
17
|
+
[source,xml]
|
|
18
|
+
----
|
|
19
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
20
|
+
<book xmlns="http://docbook.org/ns/docbook" version="5.0"
|
|
21
|
+
xml:id="my-book">
|
|
22
|
+
<info>
|
|
23
|
+
<title>My Technical Book</title>
|
|
24
|
+
<author>
|
|
25
|
+
<personname>
|
|
26
|
+
<firstname>Jane</firstname>
|
|
27
|
+
<surname>Developer</surname>
|
|
28
|
+
</personname>
|
|
29
|
+
</author>
|
|
30
|
+
<copyright>
|
|
31
|
+
<year>2025</year>
|
|
32
|
+
<holder>Acme Corp</holder>
|
|
33
|
+
</copyright>
|
|
34
|
+
</info>
|
|
35
|
+
|
|
36
|
+
<preface xml:id="preface">
|
|
37
|
+
<title>Preface</title>
|
|
38
|
+
<para>This book explains how to use the DocBook conversion tool.</para>
|
|
39
|
+
</preface>
|
|
40
|
+
|
|
41
|
+
<part xml:id="part-fundamentals">
|
|
42
|
+
<title>Part I. Fundamentals</title>
|
|
43
|
+
<chapter xml:id="ch-intro">
|
|
44
|
+
<title>Introduction</title>
|
|
45
|
+
<para>Content of the introduction chapter.</para>
|
|
46
|
+
<section xml:id="ch-intro-overview">
|
|
47
|
+
<title>Overview</title>
|
|
48
|
+
<para>Detailed overview content.</para>
|
|
49
|
+
</section>
|
|
50
|
+
</chapter>
|
|
51
|
+
<chapter xml:id="ch-setup">
|
|
52
|
+
<title>Getting Started</title>
|
|
53
|
+
<para>Setup instructions here.</para>
|
|
54
|
+
</chapter>
|
|
55
|
+
</part>
|
|
56
|
+
|
|
57
|
+
<appendix xml:id="appendix-a">
|
|
58
|
+
<title>Appendix A. Additional Resources</title>
|
|
59
|
+
<para>Supplementary material.</para>
|
|
60
|
+
</appendix>
|
|
61
|
+
|
|
62
|
+
<glossary xml:id="glossary">
|
|
63
|
+
<title>Glossary</title>
|
|
64
|
+
<glossentry>
|
|
65
|
+
<glossterm>DocBook</glossterm>
|
|
66
|
+
<glossdef>
|
|
67
|
+
<para>A semantic markup language for technical documentation.</para>
|
|
68
|
+
</glossdef>
|
|
69
|
+
</glossentry>
|
|
70
|
+
</glossary>
|
|
71
|
+
|
|
72
|
+
<bibliography xml:id="bibliography">
|
|
73
|
+
<title>References</title>
|
|
74
|
+
<bibliomixed>
|
|
75
|
+
<abbrev>DocBook5</abbrev>
|
|
76
|
+
<title>DocBook 5: The Definitive Guide</title>
|
|
77
|
+
</bibliomixed>
|
|
78
|
+
</bibliography>
|
|
79
|
+
|
|
80
|
+
<index xml:id="index"/>
|
|
81
|
+
</book>
|
|
82
|
+
----
|
|
83
|
+
|
|
84
|
+
== Step 1: Validate the input
|
|
85
|
+
|
|
86
|
+
Before conversion, validate that the XML is well-formed:
|
|
87
|
+
|
|
88
|
+
....
|
|
89
|
+
docbook validate book.xml
|
|
90
|
+
....
|
|
91
|
+
|
|
92
|
+
If the file is valid, the command prints `book.xml: valid` and exits
|
|
93
|
+
with code 0. If there are errors, they are printed to stderr and the
|
|
94
|
+
command exits with code 1.
|
|
95
|
+
|
|
96
|
+
== Step 2: Check XIncludes (if applicable)
|
|
97
|
+
|
|
98
|
+
If your book uses `<xi:include>` to pull in chapters from separate
|
|
99
|
+
files, verify that all referenced files exist and are well-formed XML.
|
|
100
|
+
XInclude resolution is enabled by default for `to-html`.
|
|
101
|
+
|
|
102
|
+
== Step 3: Convert to single-file HTML
|
|
103
|
+
|
|
104
|
+
For a self-contained HTML file:
|
|
105
|
+
|
|
106
|
+
....
|
|
107
|
+
docbook to-html book.xml -o output.html
|
|
108
|
+
....
|
|
109
|
+
|
|
110
|
+
This produces `output.html` with all data, CSS, and JavaScript
|
|
111
|
+
inlined. You can open it directly in any browser.
|
|
112
|
+
|
|
113
|
+
== Step 4: Convert to directory output
|
|
114
|
+
|
|
115
|
+
For a directory-based output with linked assets:
|
|
116
|
+
|
|
117
|
+
....
|
|
118
|
+
docbook to-html book.xml -o my-book --output-type directory
|
|
119
|
+
....
|
|
120
|
+
|
|
121
|
+
This creates a `my-book/` directory containing:
|
|
122
|
+
|
|
123
|
+
* `index.html` -- The HTML shell with the Vue SPA mount point
|
|
124
|
+
* `docbook.data.json` -- The full document data as JSON
|
|
125
|
+
* `assets/app.css` -- The compiled stylesheet
|
|
126
|
+
* `assets/app.iife.js` -- The bundled JavaScript
|
|
127
|
+
|
|
128
|
+
== Step 5: Open in browser
|
|
129
|
+
|
|
130
|
+
Open the HTML file or directory in a web browser. You should see:
|
|
131
|
+
|
|
132
|
+
* **TOC sidebar** -- A collapsible tree showing all parts, chapters,
|
|
133
|
+
and sections with their section numbers.
|
|
134
|
+
* **Section numbering** -- Parts labeled with Roman numerals (I, II),
|
|
135
|
+
chapters with Arabic numbers (1, 2), and sections with hierarchical
|
|
136
|
+
dotted numbers (1.1, 1.2.3).
|
|
137
|
+
* **Chapter navigation** -- Click any TOC entry to navigate to that
|
|
138
|
+
section.
|
|
139
|
+
* **Search** -- Use the search function to find sections by title.
|
|
140
|
+
* **Index page** -- If the book contains `<indexterm>` elements, an
|
|
141
|
+
index section with entries grouped by letter.
|
|
142
|
+
* **Settings** -- Theme, font size, reading mode, and other preferences.
|
|
143
|
+
|
|
144
|
+
== Using the Ruby API
|
|
145
|
+
|
|
146
|
+
You can also convert programmatically:
|
|
147
|
+
|
|
148
|
+
[source,ruby]
|
|
149
|
+
----
|
|
150
|
+
require "docbook"
|
|
151
|
+
|
|
152
|
+
xml = File.read("book.xml")
|
|
153
|
+
|
|
154
|
+
# Parse
|
|
155
|
+
doc = Docbook::Document.from_xml(xml)
|
|
156
|
+
|
|
157
|
+
# Resolve cross-references
|
|
158
|
+
xref = Docbook::XrefResolver.new(doc).resolve!
|
|
159
|
+
|
|
160
|
+
# Generate HTML
|
|
161
|
+
html = Docbook::Output::Html.new(
|
|
162
|
+
doc,
|
|
163
|
+
xref_resolver: xref,
|
|
164
|
+
output_mode: :single_file,
|
|
165
|
+
base_path: File.dirname(File.expand_path("book.xml"))
|
|
166
|
+
).to_html
|
|
167
|
+
|
|
168
|
+
File.write("output.html", html)
|
|
169
|
+
----
|
|
170
|
+
|
|
171
|
+
== Troubleshooting
|
|
172
|
+
|
|
173
|
+
Unsupported root element::
|
|
174
|
+
Ensure the XML root element is one of the 37 supported types listed
|
|
175
|
+
in `Document::ROOT_ELEMENT_MAP`. The most common roots are `book`,
|
|
176
|
+
`article`, and `set`.
|
|
177
|
+
|
|
178
|
+
Missing images in output::
|
|
179
|
+
The converter resolves image paths relative to the input file's
|
|
180
|
+
directory. It also searches parent directories and common prefixes
|
|
181
|
+
like `resources/`. If images are still missing, check that the
|
|
182
|
+
`fileref` attribute in `<imagedata>` points to a valid file.
|
|
183
|
+
|
|
184
|
+
XInclude errors::
|
|
185
|
+
XInclude resolution requires that referenced files exist and are
|
|
186
|
+
accessible from the input file's location. Check file paths and
|
|
187
|
+
permissions.
|
|
188
|
+
|
|
189
|
+
Empty output::
|
|
190
|
+
If the output HTML appears empty, the document may not contain any
|
|
191
|
+
recognized block elements. Ensure chapters and sections contain
|
|
192
|
+
`<para>`, `<programlisting>`, or other supported block elements.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Guides
|
|
4
|
+
nav_order: 7
|
|
5
|
+
has_children: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Guides
|
|
9
|
+
|
|
10
|
+
This section contains task-oriented tutorials that walk you through
|
|
11
|
+
common scenarios step by step. Each guide is self-contained and
|
|
12
|
+
includes complete examples you can run immediately.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Round-trip Testing
|
|
4
|
+
parent: Guides
|
|
5
|
+
nav_order: 3
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Round-trip Testing
|
|
9
|
+
|
|
10
|
+
The `docbook roundtrip` command verifies that the element model can
|
|
11
|
+
faithfully parse and re-serialize a DocBook XML document. This is
|
|
12
|
+
essential for ensuring model completeness and serialization fidelity.
|
|
13
|
+
|
|
14
|
+
== How round-trip testing works
|
|
15
|
+
|
|
16
|
+
The round-trip test performs the following sequence:
|
|
17
|
+
|
|
18
|
+
. **Parse** -- The input XML is parsed into element model objects via
|
|
19
|
+
`Document.from_xml`.
|
|
20
|
+
. **Serialize** -- The model objects are serialized back to XML using
|
|
21
|
+
`to_xml` with pretty printing enabled.
|
|
22
|
+
. **Re-parse** -- The serialized XML is parsed again.
|
|
23
|
+
. **Compare** -- If the second parse succeeds without errors, the test
|
|
24
|
+
passes.
|
|
25
|
+
|
|
26
|
+
A successful round-trip confirms that:
|
|
27
|
+
|
|
28
|
+
* All elements and attributes in the input are represented in the model.
|
|
29
|
+
* The XML serialization produces valid DocBook XML.
|
|
30
|
+
* The serialized output can be parsed again without errors.
|
|
31
|
+
|
|
32
|
+
Note that the test does not compare the original and re-serialized XML
|
|
33
|
+
strings character-by-character. Differences in whitespace, attribute
|
|
34
|
+
order, and namespace declarations are acceptable as long as the
|
|
35
|
+
re-parsing succeeds.
|
|
36
|
+
|
|
37
|
+
== Using the CLI
|
|
38
|
+
|
|
39
|
+
Test one or more files:
|
|
40
|
+
|
|
41
|
+
....
|
|
42
|
+
docbook roundtrip book.xml
|
|
43
|
+
docbook roundtrip chapter1.xml chapter2.xml chapter3.xml
|
|
44
|
+
....
|
|
45
|
+
|
|
46
|
+
For each file, the command prints either `filename.xml: OK` or
|
|
47
|
+
`filename.xml: FAIL - error message`. At the end, it prints a summary:
|
|
48
|
+
|
|
49
|
+
....
|
|
50
|
+
3 files, 0 failures
|
|
51
|
+
....
|
|
52
|
+
|
|
53
|
+
If any file fails, the command exits with code 1.
|
|
54
|
+
|
|
55
|
+
== Using in CI pipelines
|
|
56
|
+
|
|
57
|
+
Round-trip testing is valuable in continuous integration. Add a step
|
|
58
|
+
to your CI configuration that runs round-trip tests against a corpus
|
|
59
|
+
of DocBook files:
|
|
60
|
+
|
|
61
|
+
[source,yaml]
|
|
62
|
+
----
|
|
63
|
+
# GitHub Actions example
|
|
64
|
+
- name: Round-trip test
|
|
65
|
+
run: |
|
|
66
|
+
find spec/fixtures -name '*.xml' -print0 | \
|
|
67
|
+
xargs -0 bundle exec docbook roundtrip
|
|
68
|
+
----
|
|
69
|
+
|
|
70
|
+
This discovers all XML fixture files and tests them in a single
|
|
71
|
+
invocation. The command fails the build if any file does not
|
|
72
|
+
round-trip successfully.
|
|
73
|
+
|
|
74
|
+
== Ruby API
|
|
75
|
+
|
|
76
|
+
You can also run round-trip tests programmatically:
|
|
77
|
+
|
|
78
|
+
[source,ruby]
|
|
79
|
+
----
|
|
80
|
+
require "docbook"
|
|
81
|
+
|
|
82
|
+
def roundtrip_test(xml_string)
|
|
83
|
+
parsed = Docbook::Document.from_xml(xml_string)
|
|
84
|
+
serialized = parsed.to_xml(declaration: true, encoding: "utf-8")
|
|
85
|
+
reparsed = Docbook::Document.from_xml(serialized)
|
|
86
|
+
true
|
|
87
|
+
rescue => e
|
|
88
|
+
puts "Round-trip failed: #{e.message}"
|
|
89
|
+
false
|
|
90
|
+
end
|
|
91
|
+
----
|
|
92
|
+
|
|
93
|
+
== Interpreting failures
|
|
94
|
+
|
|
95
|
+
Round-trip failures typically indicate one of the following issues:
|
|
96
|
+
|
|
97
|
+
Unsupported element::
|
|
98
|
+
If the input contains an element that has no corresponding model class,
|
|
99
|
+
`Document.from_xml` raises a "Unsupported root element" error. The
|
|
100
|
+
solution is to add the missing element class.
|
|
101
|
+
|
|
102
|
+
Missing attribute::
|
|
103
|
+
If an element's XML mapping does not declare an attribute that appears
|
|
104
|
+
in the input, the attribute is silently dropped during parsing. The
|
|
105
|
+
re-serialized XML will lack the attribute. This usually manifests as
|
|
106
|
+
a different parse result on the second pass.
|
|
107
|
+
|
|
108
|
+
Broken mixed content::
|
|
109
|
+
If an element declares `mixed_content` but its child element mappings
|
|
110
|
+
are incomplete, some children may be lost during serialization. Check
|
|
111
|
+
that all expected child elements are declared in the element class.
|
|
112
|
+
|
|
113
|
+
Serialization error::
|
|
114
|
+
If the model's `to_xml` produces malformed XML (for example, due to
|
|
115
|
+
incorrect namespace handling), the re-parse step will fail with a
|
|
116
|
+
Nokogiri parse error. The error message usually identifies the line
|
|
117
|
+
and column where the problem occurs.
|
|
118
|
+
|
|
119
|
+
== Testing with XIncludes
|
|
120
|
+
|
|
121
|
+
Round-trip testing operates on the raw XML without resolving XIncludes.
|
|
122
|
+
If you want to test XInclude resolution as well, resolve the includes
|
|
123
|
+
first, then run the round-trip on the resolved document:
|
|
124
|
+
|
|
125
|
+
....
|
|
126
|
+
# Resolve XIncludes first, then round-trip the resolved XML
|
|
127
|
+
resolved = Docbook::XIncludeResolver.resolve_string(xml_string, base_path: "book.xml")
|
|
128
|
+
Docbook::Document.from_xml(resolved.to_xml)
|
|
129
|
+
....
|