java - XML 数据到 PostgreSQL 数据库

标签 java xml database parsing postgresql

<分区>

将 XML 数据(我从网页获取的数据)插入 PostgreSQL 数据库的最佳方式是什么?
我正在使用 Java,需要一些帮助才能找到将这些数据读入数据库的好方法。

最佳答案

我有一个工作实现,我可以在 PostgreSQL 中执行一切,无需额外的库。

辅助解析函数

CREATE OR REPLACE FUNCTION f_xml_extract_val(text, xml)
  RETURNS text AS
$func$
SELECT CASE
        WHEN $1 ~ '@[[:alnum:]_]+$' THEN
           (xpath($1, $2))[1]
        WHEN $1 ~* '/text()$' THEN
           (xpath($1, $2))[1]
        WHEN $1 LIKE '%/' THEN
           (xpath($1 || 'text()', $2))[1]
        ELSE
           (xpath($1 || '/text()', $2))[1]
       END;
$func$  LANGUAGE sql IMMUTABLE;

处理多个

上述实现不处理一个 xpath 中的多个属性。这是一个 overloaded f_xml_extract_val() 的版本。使用第三个参数,您可以选择 one(第一个)、alldist(不同的)值。多个值聚合成逗号分隔的字符串。

CREATE OR REPLACE FUNCTION f_xml_extract_val(_path text, _node xml, _mode text)
  RETURNS text AS
$func$
DECLARE
   _xpath text := CASE
                   WHEN $1 ~~ '%/'              THEN $1 || 'text()'
                   WHEN lower($1) ~~ '%/text()' THEN $1
                   WHEN $1 ~ '@\w+$'            THEN $1
                   ELSE                              $1 || '/text()'
                  END;
BEGIN
   -- fetch one, all or distinct values
   CASE $3
       WHEN 'one'  THEN RETURN (xpath(_xpath, $2))[1]::text;
       WHEN 'all'  THEN RETURN array_to_string(xpath(_xpath, $2), ', ');
       WHEN 'dist' THEN RETURN array_to_string(ARRAY(
            SELECT DISTINCT unnest(xpath(_xpath, $2))::text ORDER BY 1), ', ');
       ELSE RAISE EXCEPTION
          'Invalid $3: >>%<<', $3;
   END CASE;
END
$func$  LANGUAGE plpgsql;

COMMENT ON FUNCTION f_xml_extract_val(text, xml, text) IS '
Extract element of an xpath from XML document
Overloaded function to f_xml_extract_val(..)
$3 .. mode is one of: one | all | dist'

调用:

SELECT f_xml_extract_val('//city', x, 'dist');

主要部分

目标表名称:tbl;原始的。键:id:

CREATE OR REPLACE FUNCTION f_sync_from_xml()
  RETURNS boolean AS
$func$
DECLARE
   datafile text := 'path/to/my_file.xml';  -- only relative path in db dir
   myxml    xml  := pg_read_file(datafile, 0, 100000000); -- arbitrary 100 MB
BEGIN
   -- demonstrating 4 variants of how to fetch values for educational purposes
   CREATE TEMP TABLE tmp ON COMMIT DROP AS
   SELECT (xpath('//some_id/text()', x))[1]::text AS id   -- id is unique  
        , f_xml_extract_val('//col1', x)          AS col1 -- one value
        , f_xml_extract_val('//col2/', x, 'all')  AS col2 -- all values incl. dupes
        , f_xml_extract_val('//col3/', x, 'dist') AS col3 -- distinct values
   FROM   unnest(xpath('/xml/path/to/datum', myxml)) x;

   -- 1.) DELETE?

   -- 2.) UPDATE
   UPDATE tbl t
   SET   (  col_1,   col2,   col3) =
         (i.col_1, i.col2, i.col3)
   FROM   tmp i
   WHERE  t.id = i.id
   AND   (t.col_1, t.col2, t.col3) IS DISTINCT FROM
         (i.col_1, i.col2, i.col3);

   -- 3.) INSERT NEW
   INSERT INTO tbl
   SELECT i.*
   FROM   tmp i
   WHERE  NOT EXISTS (SELECT 1 FROM tbl WHERE id = i.id);
END
$func$  LANGUAGE plpgsql;

重要提示

  • 如果插入的行已经存在并且在这种情况下更新,此实现将检查主键。仅插入新行。

  • 我使用临时暂存表来加快该过程。

  • 使用 Postgres 8.49.09.1 进行测试。

  • XML 必须格式正确。

  • pg_read_file() 对此有限制。 The manual :

    Use of these functions is restricted to superusers.

    和:

    Only files within the database cluster directory and the log_directory can be accessed.

所以你必须把你的源文件放在那里 - 或者创建一个符号链接(symbolic link)到你的实际文件/目录。

或者您可以根据您的情况通过 Java 提供文件(我在 Postgres 中完成了这一切)。

或者您可以将数据导入临时表的 1 行的 1 列,然后从那里获取。

或者您可以像本related answer on dba.SE 中演示的那样使用lo_import .

本博客post by Scott Bailey帮助了我。

关于java - XML 数据到 PostgreSQL 数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7491479/

相关文章:

sql - 我如何使用 PostgreSQL 的 DISTINCT ON 子句来返回重复项的计数?

java - java eclipse 错误的 Minecraft 克隆

java - 用 A* 算法解决 8 难题

Java 库文件错误

sql - 为 sp_xml_preparedocument 配置 namespace

xml - 使用 XSLT 将 XML 中的日期和转换为 UTC 时区

java - 如何使用 JAXB (Intellij Idea) 从多个 xsd 生成 Java 类

java - 将整数值添加到数据库表错误

java - 在 Android 上使用 MySQL

java - 通过基本身份验证端点创建 JSON Web token ?下拉 Sprite