【问题标题】:Not able to read values from xml in postgres无法从 postgres 中的 xml 读取值
【发布时间】:2022-07-02 09:03:02
【问题描述】:

我正在尝试从 xml 中读取并将它们插入到临时表中并返回该表作为结果。下面是我正在尝试的 Postgres 函数

CREATE OR REPLACE FUNCTION public.xml(
    )
    RETURNS TABLE(name character varying, description character varying, parentpid character varying, level integer, nodenumber character varying, displayorder integer, iscustom boolean) 
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE PARALLEL UNSAFE
    ROWS 1000

AS $BODY$
declare
xmlvalue text := '<ArrayOfClientProcess>
<ClientProcess><Id>0</Id><IsActive>false</IsActive><LastModifiedBy>email</LastModifiedBy>
<LastModifiedOn>2022-04-27</LastModifiedOn><ClientId>0</ClientId><ProcessId>0</ProcessId>
<IsUserSelected>false</IsUserSelected><IndustryId>0</IndustryId><Occurrence>false</Occurrence><ParentPId>NULL</ParentPId>
<CAMSAssigned>false</CAMSAssigned><KPIAssigned>false</KPIAssigned><IsTechVariantAvailable>false</IsTechVariantAvailable>
<IBSCentralId>0</IBSCentralId><MasterId>0</MasterId><MasterCentralId>0</MasterCentralId><SegmentId>0</SegmentId><CAMId>0</CAMId>
<IsEPCAvailable>false</IsEPCAvailable><IsVariantAvailable>false</IsVariantAvailable><IsSubvariantAvailable>false</IsSubvariantAvailable>
<LOMVariantId>0</LOMVariantId><ProcessLevel>0</ProcessLevel><OperationsPresence>false</OperationsPresence><IsDigitalImpact>false</IsDigitalImpact>
<IsCrossIndustry>false</IsCrossIndustry><Name>FinanceCustom</Name><Description>Finance</Description><ParentId>0</ParentId><Level>0</Level>
<NodeNumber>0</NodeNumber><GeographyId>0</GeographyId><DisplayOrder>0</DisplayOrder><IsCustom>true</IsCustom><IsCustomMapped>false</IsCustomMapped>
<IsProcessChecked>false</IsProcessChecked><islinkedwithCPA>0</islinkedwithCPA><ProcessIdfromCPA>0</ProcessIdfromCPA>
<IsProcessCheckedOnLeftPane>false</IsProcessCheckedOnLeftPane></ClientProcess></ArrayOfClientProcess>';
begin
CREATE TEMPORARY TABLE tempClientProcess(name character varying,
description character varying,
parentpid character varying,
level integer,
nodenumber character varying,
displayorder integer,
iscustom boolean);

with data as ( 
select xmlvalue::xml val)
INSERT INTO tempClientProcess(name,description,parentpid,level,nodenumber,displayorder,iscustom)

SELECT d.name,d.description,d.parentpid,d.level,d.nodenumber,d.displayorder,d.iscustom 
FROM   data x, 
XMLTABLE('/ArrayOfClientProcess/ClientProcess' 
PASSING val 
COLUMNS  
name character varying PATH 'name',
description character varying PATH 'description',
parentpid character varying PATH 'parentpid',
level integer PATH 'level',
nodenumber character varying PATH 'nodenumber',
displayorder integer PATH 'displayorder',
iscustom boolean PATH 'iscustom') as d; 

return query
select * from tempClientProcess ;
drop table tempClientProcess;
end;
$BODY$;

当我执行该函数时,临时表将 null 显示为列值。让我觉得它可能无法正确读取 xml 中的值。我在解析时可能做错了什么。

【问题讨论】:

  • @JGH 哎呀。已编辑

标签: postgresql plpgsql xmltable


【解决方案1】:

假设无效的LastModifiedOn&gt; 是复制和粘贴错误,则错误出现在列的 XPATH 表达式中。标签名称区分大小写,因此您需要此列定义:

name character varying PATH 'Name',
description character varying PATH 'Description',
parentpid character varying PATH 'ParentPId',
level integer PATH 'Level',
nodenumber character varying PATH 'NodeNumber',
displayorder integer PATH 'DisplayOrder',
iscustom boolean PATH 'IsCustom' 

注意在函数中创建临时表是完全没有必要的,可以直接返回xmltable()的结果

CREATE OR REPLACE FUNCTION xml()
    RETURNS TABLE(name character varying, description character varying, parentpid character varying, level integer, nodenumber character varying, displayorder integer, iscustom boolean) 
    LANGUAGE plpgsql
    ROWS 1
AS $BODY$
declare
  xmlvalue xml := 
    '<ArrayOfClientProcess>
    <ClientProcess><Id>0</Id><IsActive>false</IsActive><LastModifiedBy>email</LastModifiedBy>
    <LastModifiedOn>2022-04-27</LastModifiedOn><ClientId>0</ClientId><ProcessId>0</ProcessId>
    <IsUserSelected>false</IsUserSelected><IndustryId>0</IndustryId><Occurrence>false</Occurrence><ParentPId>NULL</ParentPId>
    <CAMSAssigned>false</CAMSAssigned><KPIAssigned>false</KPIAssigned><IsTechVariantAvailable>false</IsTechVariantAvailable>
    <IBSCentralId>0</IBSCentralId><MasterId>0</MasterId><MasterCentralId>0</MasterCentralId><SegmentId>0</SegmentId><CAMId>0</CAMId>
    <IsEPCAvailable>false</IsEPCAvailable><IsVariantAvailable>false</IsVariantAvailable><IsSubvariantAvailable>false</IsSubvariantAvailable>
    <LOMVariantId>0</LOMVariantId><ProcessLevel>0</ProcessLevel><OperationsPresence>false</OperationsPresence><IsDigitalImpact>false</IsDigitalImpact>
    <IsCrossIndustry>false</IsCrossIndustry><Name>FinanceCustom</Name><Description>Finance</Description><ParentId>0</ParentId><Level>0</Level>
    <NodeNumber>0</NodeNumber><GeographyId>0</GeographyId><DisplayOrder>0</DisplayOrder><IsCustom>true</IsCustom><IsCustomMapped>false</IsCustomMapped>
    <IsProcessChecked>false</IsProcessChecked><islinkedwithCPA>0</islinkedwithCPA><ProcessIdfromCPA>0</ProcessIdfromCPA>
    <IsProcessCheckedOnLeftPane>false</IsProcessCheckedOnLeftPane></ClientProcess>
    </ArrayOfClientProcess>';
begin
  return query
    SELECT d.name,d.description,d.parentpid,d.level,d.nodenumber,d.displayorder,d.iscustom 
    FROM XMLTABLE('/ArrayOfClientProcess/ClientProcess' 
                  PASSING xmlvalue
                  COLUMNS  
                    name character varying PATH 'Name',
                    description character varying PATH 'Description',
                    parentpid character varying PATH 'ParentPId',
                    level integer PATH 'Level',
                    nodenumber character varying PATH 'NodeNumber',
                    displayorder integer PATH 'DisplayOrder',
                    iscustom boolean PATH 'IsCustom') as d; 
end;
$BODY$;

事实上,您甚至不需要为此使用 PL/pgSQL。一个简单的language sql 也可以。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-19
    • 2020-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多