xml - 在 PostgreSQL 中搜索 XML 文档
问题描述
所以我目前有一个使用 psql 的非常简单的表,如下所示:
Table "public.test"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+----------------------------------
id | integer | | not null | nextval('test_id_seq'::regclass)
blah | xml | | |
Indexes:
"test_pkey" PRIMARY KEY, btree (id)
目前有这个数据:
id | blah
----+------------------
1 | =juego_Tipo1.xml
(1 row)
文件“juego_Tipo1.xml”如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Gamificacion Id="1">
<titulo>NomTitulo</titulo>
<autor>NomAutor</autor>
<preguntas tipo="Tipo1">
<pregunta EmpiezaPor="" comodin50="" id="preg_0" sol="A">
<temaPregunta/>
<enunciado numLineas="3">Este es el enunciado 1</enunciado>
<respuesta num="1" numLetras="5" numLineas="1">Respuesta A</respuesta>
<respuesta num="2" numLetras="5" numLineas="1">Respuesta B</respuesta>
<respuesta num="3" numLetras="5" numLineas="1">Respuesta C</respuesta>
<respuesta num="4" numLetras="5" numLineas="1">Respuesta D</respuesta>
<pista id="1" numLineas="numLineas"/>
</pregunta>
<pregunta EmpiezaPor="" comodin50="" id="preg_1" sol="B">
<temaPregunta/>
<enunciado numLineas="3">Enunciado 2</enunciado>
<respuesta num="1" numLetras="5" numLineas="1">Respuesta A 2 </respuesta>
<respuesta num="2" numLetras="5" numLineas="1">Respuesta B 2</respuesta>
<respuesta num="3" numLetras="5" numLineas="1">Respuesta C 2</respuesta>
<respuesta num="4" numLetras="5" numLineas="1">Respuesta D 2</respuesta>
<pista id="1" numLineas="numLineas"/></pregunta></preguntas></Gamificacion>
我要做的是检查“respuesta”中的任何元素是否是“Respuesta A”。如果是这样,我想返回满足该条件的文件(或文件)的名称。
我尝试使用该xpath(xpath, xml [, nsarray])
函数,但它会引发此错误:
ERROR: could not parse XML document
DETAIL: line 1: Start tag expected, '<' not found
=juego_Tipo1.xml
我假设这是因为该函数仅在“blah”中的内容是 xml 而不是 xml 文件时才有效。
这可能吗?如果没有,我应该如何解决这个问题?
我目前使用的 Postgresql 是 10.15。
我使用以下命令创建了表:
create table test(id serial primary key, blah xml);
我已经使用这些命令填充了表格:
\set test = 'juego_Tipo1.xml'
INSERT INTO test(blah) values (:'test');
注意:“juego_Tipo1.xml”应该是当前目录中存在的如上所示内容的文件。
解决方案
这个问题并不像乍看起来那么简单,至少对我来说是这样。以下是我理解的复制和解决它的过程,尽管可能是错误的。如果不正确,至少我希望这将是朝着正确方向迈出的第一步,或者为您提供一些解决方法的线索,因为在这个问题中您甚至没有尝试过。
1.- 在临时目录中创建输入数据。
mkdir -p /tmp/stackoverflow/{initdb,xmlfiles} && cd /tmp/stackoverflow
2.- 使用您喜欢的编辑器编辑 sql 文件:
vim initdb/setup.sql
并添加:
create table test(id serial primary key, blah xml);
insert into test(blah)
values
('/xmlfiles/juego_Tipo1.xml'),
('/xmlfiles/juego_Tipo2.xml');
create function file_with_correct_answer(file text)
returns table(filename text) as $$
begin
file := quote_literal(file);
create temp table xmldata (data text);
create temp table t (filename text);
execute 'insert into t (filename) values (' || file || ')';
execute 'copy xmldata from ' || file;
return query
with t2(fn, linexml) as (select t.filename, string_agg(data, '')::xml from xmldata cross join t group by t.filename)
select fn from t2 where xpath_exists('//respuesta[text() = "Respuesta A"]', linexml);
drop table xmldata;
drop table t;
end;
$$ language plpgsql;
3.- 创建两个xml文件来检查成功和失败的条件:
vim xmlfiles/juego_Tipo1.xml
有数据:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Gamificacion Id="1">
<titulo>NomTitulo</titulo>
<autor>NomAutor</autor>
<preguntas tipo="Tipo1">
<pregunta EmpiezaPor="" comodin50="" id="preg_0" sol="A">
<temaPregunta/>
<enunciado numLineas="3">Este es el enunciado 1</enunciado>
<respuesta num="1" numLetras="5" numLineas="1">Respuesta A</respuesta>
<respuesta num="2" numLetras="5" numLineas="1">Respuesta B</respuesta>
<respuesta num="3" numLetras="5" numLineas="1">Respuesta C</respuesta>
<respuesta num="4" numLetras="5" numLineas="1">Respuesta D</respuesta>
<pista id="1" numLineas="numLineas"/>
</pregunta>
<pregunta EmpiezaPor="" comodin50="" id="preg_1" sol="B">
<temaPregunta/>
<enunciado numLineas="3">Enunciado 2</enunciado>
<respuesta num="1" numLetras="5" numLineas="1">Respuesta A 2 </respuesta>
<respuesta num="2" numLetras="5" numLineas="1">Respuesta B 2</respuesta>
<respuesta num="3" numLetras="5" numLineas="1">Respuesta C 2</respuesta>
<respuesta num="4" numLetras="5" numLineas="1">Respuesta D 2</respuesta>
<pista id="1" numLineas="numLineas"/></pregunta></preguntas></Gamificacion>
和
vim xmlfiles/juego_Tipo2.xml
有数据:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Gamificacion Id="1">
<titulo>NomTitulo</titulo>
<autor>NomAutor</autor>
<preguntas tipo="Tipo1">
<pregunta EmpiezaPor="" comodin50="" id="preg_0" sol="A">
<temaPregunta/>
<enunciado numLineas="3">Este es el enunciado 1</enunciado>
<respuesta num="1" numLetras="5" numLineas="1">Respuesta E</respuesta>
<respuesta num="2" numLetras="5" numLineas="1">Respuesta B</respuesta>
<respuesta num="3" numLetras="5" numLineas="1">Respuesta C</respuesta>
<respuesta num="4" numLetras="5" numLineas="1">Respuesta D</respuesta>
<pista id="1" numLineas="numLineas"/>
</pregunta>
<pregunta EmpiezaPor="" comodin50="" id="preg_1" sol="B">
<temaPregunta/>
<enunciado numLineas="3">Enunciado 2</enunciado>
<respuesta num="1" numLetras="5" numLineas="1">Respuesta A 2 </respuesta>
<respuesta num="2" numLetras="5" numLineas="1">Respuesta B 2</respuesta>
<respuesta num="3" numLetras="5" numLineas="1">Respuesta C 2</respuesta>
<respuesta num="4" numLetras="5" numLineas="1">Respuesta D 2</respuesta>
<pista id="1" numLineas="numLineas"/></pregunta></preguntas></Gamificacion>
4.- 为 Postgresql 使用 docker 容器:
docker container run --rm -it \
--name stack-overflow \
-p 5432:5432 \
-e POSTGRES_PASSWORD=black \
-v /tmp/stackoverflow/xmlfiles:/xmlfiles \
-v /tmp/stackoverflow/initdb:/docker-entrypoint-initdb.d \
postgres
5.- 在容器中使用 psql:
docker run -it --rm --link stack-overflow:postgres postgres \
psql -h postgres -U postgres
6.- 与客户端执行查询(blah
字段应该是text
类型)psql
:
select file_with_correct_answer(cast(blah as text)) from test;
产生:
file_with_correct_answer
---------------------------
/xmlfiles/juego_Tipo1.xml
(1 row)
推荐阅读
- javascript - 将 HTML 数据从浏览器导出到 html 文件
- r - 当原始因子水平由字符串组成时,因子到数字的正确转换是什么?
- python - Python:列表内容的所有可能组合
- javascript - 在 React 应用程序内的 JavaScript 中以特定方式合并两个数组
- java - 删除标记并同时删除firestore中的文档
- bots - 计数游戏不和谐js
- ruby-on-rails - 需要在 rails Helper 中从 Jbuilder 创建一个 json 字符串
- docker - Docker:如何将自己添加到 Windows 10 主页上的 docker-users 组?
- python - Python 中的一行平均值(使用 Pandas 读取 CSV 文件)
- node.js - Angular - 如何导入 googleapis 库?