1

1

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命令指示解析器在遇到documentsection类型的节点时调用特定代码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::3demo::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+将默认始终刷新内容。

相关内容