无法从 postgres 中的 xml 读取值

Not able to read values from xml in postgres

我正在尝试从 xml 中读取并将它们插入到 table 和 return 中,结果是 table。下面是我正在尝试使用的 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$;

当我执行该函数时,临时 table 将空值显示为列值。让我觉得它可能无法正确读取 xml 中的值。我在解析时可能做错了什么。任何线索都会有所帮助。谢谢

假设无效的 LastModifiedOn> 是复制和粘贴错误,错误出在列的 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' 

注意在函数中创建临时table是完全没有必要的,你可以return直接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 也可以。