PostgreSQL 9.4.4 中文手册
上一页 | 上一级 | 附录 F. 额外提供的模块 | 下一页

# F.45. xml2

`xml2`模块提供XPath查询和XSLT功能。

## F.45.1. 弃用通知

从PostgreSQL 8.3开始，在内核服务器中有一个基于SQL/XML标准的XML相关的功能。 这个功能包含了XML语法检查和XPath查询，这也是这个模块的包含的，甚至更多，不过API一点也不兼容。 计划在未来的PostgreSQL版本中删除这个模块，支持新的标准的API，所以鼓励你尝试转换你的应用。 如果你发现这个模块的某些功能在一个适当形式的更新的API中不可用， 请解释你的问题到`<pgsql-hackers@postgresql.org>`，以便解决这个缺陷。

## F.45.2. 功能说明

表 F-32显示了这个模块提供的函数。 这些函数提供了简单的XMP解析和XPath查询。所有参数都是`text`类型的， 所以为了简化没有显示。

表 F-32. 函数

函数 | 返回 | 描述
--- | --- | ---
`xml_is_well_formed(document)` | `bool` | 解析它的参数中的文件正文，并且如果文件是格式良好的XML则返回真。 （注意：在PostgreSQL 8.2之前，这个函数称为`xml_valid()`。 这是错误的名字，因为在XML中有效性和良构性有不同的含义。 老的名字仍然可用，但是已经废弃了。）
`xpath_string(document, query)` | `text` | 这个函数在提供的文件上评估XPath查询，并转换结果到指定的类型。
`xpath_number(document, query)` | `float4`
`xpath_bool(document, query)` | `bool`
`xpath_nodeset(document, query, toptag, itemtag)` | `text` | 在文件上评估查询并将结果包装在XML标签中。如果结果是多值的，那么输出将看起来像：
    <toptag>
    <itemtag>Value 1 which could be an XML fragment</itemtag>
    <itemtag>Value 2....</itemtag>
    </toptag>
如果`toptag`或`itemtag`中的任意一个是空字符串，那么省略相关的标签。
`xpath_nodeset(document, query)` | `text` | 类似于`xpath_nodeset(document, query, toptag, itemtag)`，但是结果省略两个标签。
`xpath_nodeset(document, query, itemtag)` | `text` | 类似于`xpath_nodeset(document, query, toptag, itemtag)`，但是结果省略`toptag`。
`xpath_list(document, query, separator)` | `text` | 这个函数返回由指定的分隔符分开的多个值，例如如果分隔符是`,`， 返回值是`Value 1,Value 2,Value 3`。
`xpath_list(document, query)` | `text` | 这是一个对于使用`,`作为分隔符的以上函数的包装器。

## F.45.3. `xpath_table`

    xpath_table(text key, text document, text relation, text xpaths, text criteria) returns setof record

`xpath_table`是一个表函数，在每一组文档上计算一组XPath查询， 并作为一个表返回结果。原始文档表的主键字段作为结果的第一个字段返回， 因此结果集可以容易的用于连接。参数在表 F-33中描述。

表 F-33. `xpath_table` 参数

参数 | 描述
--- | ---
`key` | "key"字段的名字—这只是用作输出表的第一个字段，也就是， 它识别每个传来的输出行的记录（请参见下面关于多行值的注释）
`document` | 包含XML文档的字段名
`relation` | 包含文档的表或视图的名字
`xpaths` | 一个或多个XPath表达式，由`|`分隔
`criteria` | WHERE子句的内容。这个不能省略，所以如果你想要在关系中处理所有的行， 那么使用`true`或`1=1`

这些参数（除了XPath字符串）只是代替一个纯SQL SELECT语句， 所以你有一些灵活性—该语句是

`SELECT <key>, <document> FROM <relation> WHERE <criteria>`

所以这些参数可以是任何在这些特定位置的有效值。 这个SELECT的结果需要返回正好两个字段（除非你尝试为key或document列出多个字段）。 注意这个简单的方法需要验证任何用户提供的值，以避免SQL注入攻击。

该函数必须用于`FROM`表达式中，用一个`AS`子句指定输出字段；例如

    SELECT * FROM
    xpath_table('article_id',
                'article_xml',
                'articles',
                '/article/author|/article/pages|/article/title',
                'date_entered > ''2003-01-01'' ')
    AS t(article_id integer, author text, page_count integer, title text);

`AS`子句定义输出表中字段的名字和类型。第一个是"key"字段， 剩余的对应于XPath查询。如果XPath查询多于结果字段，那么额外的查询将被忽略。 如果结果字段多于XPath查询，那么额外的字段将为空。

请注意，这个示例定义`page_count`的结果字段为一个整数。 该函数内部处理字符串的表示，所以当你说你在输出中想要一个整数时， 它将接收XPath结果的字符串表示，并使用PostgreSQL输入函数将它转换为一个整数 （或者任何`AS`子句要求的类型）。如果它不能这么做则导致一个错误— 例如，如果结果为空—所以如果你认为你的数据有任何问题， 你可能想要坚持`text`作为该字段的类型。

调用的`SELECT`语句不需要只是`SELECT *`— 它可以通过名字或链接输出字段到其他的表引用输出字段。 该函数产生一个虚拟表，用该虚拟表你可以执行任何你想要的操作 （例如，聚合、链接、排序等等）。所以我们也可以将：

    SELECT t.title, p.fullname, p.email
    FROM xpath_table('article_id', 'article_xml', 'articles',
                     '/article/title|/article/author/@id',
                     'xpath_string(article_xml,''/article/@date'') > ''2003-03-20'' ')
           AS t(article_id integer, title text, author_id integer),
         tblPeopleInfo AS p
    WHERE t.author_id = p.person_id;

作为一个更复杂的示例。当然，为了方便，你可以将所有这些包装到一个视图中。

### F.45.3.1. 多值的结果

`xpath_table`函数假设每个XPath查询的结果可能是多值的， 所以该函数返回的行数可能和输入文档的行数不同。 返回的第一行包含每个查询的第一个结果，第二行包含每个查询的第二个结果。 如果其中的一个查询比其他查询的值少，那么将返回空值。

在某些情况下，用户知道一个给定的XPath查询将只返回一个结果（可能是一个唯一文档标识符）— 如果和返回多个结果的XPath查询一起使用，那么唯一值结果将只在结果的第一行出现。 这个问题的解决方法是使用该关键字段作为一个更简单的XPath查询连接的一部分。 示例：

    CREATE TABLE test (
        id int PRIMARY KEY,
        xml text
    );

    INSERT INTO test VALUES (1, '<doc num="C1">
    <line num="L1"><a>1</a><b>2</b><c>3</c></line>
    <line num="L2"><a>11</a><b>22</b><c>33</c></line>
    </doc>');

    INSERT INTO test VALUES (2, '<doc num="C2">
    <line num="L1"><a>111</a><b>222</b><c>333</c></line>
    <line num="L2"><a>111</a><b>222</b><c>333</c></line>
    </doc>');

    SELECT * FROM
      xpath_table('id','xml','test',
                  '/doc/@num|/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c',
                  'true')
      AS t(id int, doc_num varchar(10), line_num varchar(10), val1 int, val2 int, val3 int)
    WHERE id = 1 ORDER BY doc_num, line_num

     id | doc_num | line_num | val1 | val2 | val3
    ----+---------+----------+------+------+------
      1 | C1      | L1       |    1 |    2 |    3
      1 |         | L2       |   11 |   22 |   33

要在每个行上获得`doc_num`，解决方法是使用两个`xpath_table` 的调用并连接结果：

    SELECT t.*,i.doc_num FROM
      xpath_table('id', 'xml', 'test',
                  '/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c',
                  'true')
        AS t(id int, line_num varchar(10), val1 int, val2 int, val3 int),
      xpath_table('id', 'xml', 'test', '/doc/@num', 'true')
        AS i(id int, doc_num varchar(10))
    WHERE i.id=t.id AND i.id=1
    ORDER BY doc_num, line_num;

     id | line_num | val1 | val2 | val3 | doc_num
    ----+----------+------+------+------+---------
      1 | L1       |    1 |    2 |    3 | C1
      1 | L2       |   11 |   22 |   33 | C1
    (2 rows)

## F.45.4. XSLT 函数

如果安装了libxslt，那么下列的函数是可用的：

### F.45.4.1. `xslt_process`

    xslt_process(text document, text stylesheet, text paramlist) returns text

这个函数应用XSL样式表到文档并返回转换了的结果。`paramlist` 是一个在转换中使用的参数分配列表，以格式`a=1,b=2`指定。 请注意，参数分析是非常简单的：参数值不能包含逗号！

也有一个两参数的`xslt_process`版本，不传递任何参数到转换。

## F.45.5. 作者

John Gray `<jgray@azuli.co.uk>`

这个模块的发展是由Torchbox Ltd. (www.torchbox.com)赞助的。 它和PostgreSQL有一样的BSD许可证。

上一页 | 起始页 | 下一页
uuid-ossp | 上一级 | 额外提供的程序