ConTeXt 提供了一种管理 XML 文件的方法。我之所以使用此功能是因为需要能够以 PDF 格式发布 xml 数据以获取目录或其他技术文档。
ConTeXt 文档引用了描述可用命令。
下面的示例引用了上面文档中的示例中的一个简单的 xml 文件 tken:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<section>
<title>Some title</title>
<content>
<p>a paragraph of text</p>
<p>another paragraph of text</p>
</content>
</section>
<section>
<title>Some title2</title>
<content>
<p>a paragraph of text2</p>
<p>another paragraph of text2</p>
</content>
</section>
</document>
1
最简单的方法是依靠可用的命令来探索 xml 树,如下面的代码所示。
\startxmlsetups xml:demo:base
\xmlsetsetup{#1}{*}{-}
\xmlsetsetup{#1}{document|section|content|p}{xml:demo:*}
\stopxmlsetups
\xmlregisterdocumentsetup{demo}{xml:demo:base}
\startxmlsetups xml:demo:document
\xmlflush{#1}
\stopxmlsetups
\startxmlsetups xml:demo:section
\xmlflush{#1}
\stopxmlsetups
\startxmlsetups xml:demo:content
\xmlflush{#1} \\
\stopxmlsetups
\startxmlsetups xml:demo:p
\xmlflush{#1} \\
\stopxmlsetups
\starttext
\xmlprocessfile{demo}{demo.xml}{}
\stoptext
该\xmlsetup
命令指示解析器在遇到document
、section
类型的节点时调用特定代码p
。如果无需执行任何操作,则命令\xmlflush{#1}
将起点返回给解析器以继续探索。当解析器到达树的叶子时,命令将返回\xmlflush{#1}
该节点的内容。运行代码我们得到:
a paragraph of text
another paragraph of text
a paragraph of text2
another paragraph of text2
2
在某些情况下,我们可能只想检索节点的子集,<p>
但如果没有任何属性,则无法做到这一点。一种可能的解决方案来自用于解析的机制,即将 id 关联到访问的节点。
\startxmlsetups xml:demo:base
\xmlsetsetup{#1}{*}{-}
\xmlsetsetup{#1}{document|section|content|p}{xml:demo:*}
\stopxmlsetups
\xmlregisterdocumentsetup{demo}{xml:demo:base}
\startxmlsetups xml:demo:document
\xmlflush{#1}
\stopxmlsetups
\startxmlsetups xml:demo:section
SECTION\\
\xmlflush{#1}
\\
\stopxmlsetups
\startxmlsetups xml:demo:content
level 2 -> \xmlflush{demo::2} \\
level 5 -> \xmlflush{demo::5} \\
level 6 -> \xmlflush{demo::6} \\
level 7 -> \xmlflush{demo::7} \\
level 8 -> \xmlflush{demo::8} \\
\stopxmlsetups
\starttext
\xmlprocessfile{demo}{demo.xml}{}
\stoptext
我们得到的是:
SECTION
level 2 -> xml version="1.0" encoding="UTF-8”
level 5 -> Some title
level 6 ->
level 7 -> a paragraph of text
level 8 -> another paragraph of text
SECTION
level 2 -> xml version="1.0" encoding="UTF-8”
level 5 -> Some title
level 6 ->
level 7 -> a paragraph of text
level 8 -> another paragraph of text
请注意,使用demo::3
和demo::4
会返回错误。显然这些 id 指的是节点<document>
和<section>
,不包含任何文本。尽管节点也不<content>
包含任何文本,但使用demo::6
会返回空字符串,而不是错误。为什么会发生这种情况?
另一件事是,id 相对于整个树是绝对的。如果我们想获取第二个<section>
节点的内容,我们必须使用以下 id。例如demo::10
返回“Some title2”:
3
文档建议使用不同的方法来处理相对引用,即使用命令\xmlfirst
。代码如下:
\startxmlsetups xml:demo:section
SECTION\\
\xmlfirst{#1}{/title}
\xmlfirst{#1}{/content}
\\
\stopxmlsetups
但输出是:
SECTION
SECTION
我使用的是 OS X 10.12.5,ConTeXt 是通过 TeX 发行版提供的。同样的问题也曾被描述过这里,但没有解决方案。
你有什么建议吗?
即使修改了以下方法,也没有得到任何结果,即使在继续搜索\xmlflush{#1}
时插入命令也是如此。这可能是解析器卡住了。xml:demo:section
\startxmlsetups xml:demo:section
SECTION\\
\xmlfirst{#1}{/title}
\\
\stopxmlsetups
\startxmlsetups xml:demo:content
\xmlflush{#1}
\stopxmlsetups
4
我现在使用的解决方案利用以下\xmltext
命令:
\startxmlsetups xml:demo:section
SECTION\\
\xmltext{#1}{./title}
\\
\stopxmlsetups
提供输出
SECTION
Some title
SECTION
Some title2
5
类似的解决方案利用了 Lua。
\registerctxluafile{luafunction}{}
\startxmlsetups xml:demo:base
\xmlsetsetup{#1}{*}{-}
\xmlsetsetup{#1}{document|section|content|p}{xml:demo:*}
\stopxmlsetups
\xmlregisterdocumentsetup{demo}{xml:demo:base}
\startxmlsetups xml:demo:document
\xmlflush{#1}
\stopxmlsetups
\startxmlsetups xml:demo:section
SECTION\\
\xmlfunction{#1}{section}
\\
\stopxmlsetups
\starttext
\xmlprocessfile{demo}{demo.xml}{}
\stoptext
并在文件中定义正确的 Lua 函数luafunction.lua
:
function xml.functions.section(t)
context(xml.text(t,"./title"))
end
还有其他建议或不同的方法吗?
答案1
为了\xmlfirst
工作,请删除该行\xmlsetsetup{#1}{*}{-}
。
来自文档(链接在问题中):
以下行:
\xmlsetsetup{demo}{*}{-}
将每个元素的默认设置设置为“忽略它”。A
+
将默认始终刷新内容。