将 2 个单独的 XMLType 记录合并到一个 xml 文件中
Posted
技术标签:
【中文标题】将 2 个单独的 XMLType 记录合并到一个 xml 文件中【英文标题】:Combine 2 seperate XMLType records into one xml file 【发布时间】:2016-03-15 08:05:36 【问题描述】:我有两个单独的表,其中一个 XML 类型字段包含需要组合并创建为文件的数据。
表 1 包含 Soap 信封消息数据,表 2 包含 SOAP 附件正文 - 在本例中为 XML 格式的发票数据。
表使用 batch_id、data_id 和 run_id 相互链接,因此表 1 是一批发票的主数据,其中 run_id 和 data_id 作为标识符。表1中的每条记录在明细表(表2)中都有一条相关记录
表 1:Batch_ID (int)、Data_ID (int)、Run_ID (int)、SOAP_XML(XmlType 字段) 表 2:Batch_ID (int)、Data_ID (int)、Run_ID (int)、INVOICE_XML(XmlType 字段)我只是想创建一个函数或过程将这些 XMLType 数据组合到一个 XML 文件中 - 一个文件包含一个批次 id 的所有记录,所以我需要循环两个表中的每个 data_id。
我曾尝试使用 XMLConcat、XMLRoot、XMLElement 函数,但未能避免最终 XML 文件中的额外元素 - 最终结果必须具有与 XMLType 字段中当前完全相同的数据 - 仅将这两个单独组合记录到一个 XML 文件中(SOAP ENVELOPE + SOAP 附件)
我想有一个简单的解决方案,但在尝试了不同的解决方案后,还没有找到任何直接这样做的解决方案,有什么建议吗?
表 1:XMLType 数据示例
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:eb="http://www.oasis-open.org/committees/ebxml-msg/schema/msg-header-2_0.xsd">
<SOAP-ENV:Header>
<eb:MessageHeader xmlns:eb="http://www.oasis-open.org/committees/ebxml-msg/schema/msg-header-2_0.xsd" SOAP-ENV:mustUnderstand="1" eb:id="xxxxxxxxxxxxxxxxxxxxxxxx">
<eb:From>
<eb:PartyId>xxxxxxxxxxxxxxxxxxx</eb:PartyId>
<eb:Role>Sender</eb:Role>
</eb:From>
<eb:From>
<eb:PartyId>xxxxxxxxxxxxx</eb:PartyId>
<eb:Role>Intermediator</eb:Role>
</eb:From>
<eb:To>
<eb:PartyId>xxxxxxxxxxxxxxxxxx</eb:PartyId>
<eb:Role>Receiver</eb:Role>
</eb:To>
<eb:To>
<eb:PartyId>xxxxxxxxxxxxx</eb:PartyId>
<eb:Role>Intermediator</eb:Role>
</eb:To>
<eb:CPAId>yoursandmycpa</eb:CPAId>
<eb:ConversationId>xxxxxxxxxx</eb:ConversationId>
<eb:Service/>
<eb:Action/>
<eb:MessageData>
<eb:MessageId>xxxxxxx</eb:MessageId>
<eb:Timestamp>2016-03-01T10:26:04</eb:Timestamp>
<eb:RefToMessageId/>
</eb:MessageData>
</eb:MessageHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<eb:Manifest eb:id="Manifest" eb:version="2.0">
<eb:Reference eb:id="Invoice" xlink:href="xxxxxx">
<eb:Schema eb:location="Invoice.xsd" eb:version="1.0"/>
</eb:Reference>
</eb:Manifest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
表 2:XMLType 示例
<?xml version="1.0" encoding="ISO-8859-15"?>
<?xml-stylesheet type="text/xsl" href="Invoice.xsl"?>
<Invoice Version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Invoice.xsd">
<SellerPartyDetails>
<SellerPartyIdentifier>xxxxxxxxxxxxxxx</SellerPartyIdentifier>
<SellerOrganisationName>xxxxxxxxxxxxxxxxxxxxxxxx</SellerOrganisationName>
<SellerOrganisationTaxCode>xxxxxxxxxxxxx</SellerOrganisationTaxCode>
<SellerPostalAddressDetails>
<SellerStreetName>xxxxxxxxxxxxxxxxxx</SellerStreetName>
<SellerTownName>xxxxxxxxxxxxxxxxxxxxxx</SellerTownName>
<SellerPostCodeIdentifier>xxxxxxxxxxxxxxxxx</SellerPostCodeIdentifier>
</SellerPostalAddressDetails>
</SellerPartyDetails>
</Invoice>
所需的结果数据文件只是表 1 和 2 记录的组合 - 如下所示:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:eb="http://www.oasis-open.org/committees/ebxml-msg/schema/msg-header-2_0.xsd">
<SOAP-ENV:Header>
<eb:MessageHeader xmlns:eb="http://www.oasis-open.org/committees/ebxml-msg/schema/msg-header-2_0.xsd" SOAP-ENV:mustUnderstand="1" eb:id="xxxxxxxxxxxxxxxxxxxxxxxx">
<eb:From>
<eb:PartyId>xxxxxxxxxxxxxxxxxxx</eb:PartyId>
<eb:Role>Sender</eb:Role>
</eb:From>
<eb:From>
<eb:PartyId>xxxxxxxxxxxxx</eb:PartyId>
<eb:Role>Intermediator</eb:Role>
</eb:From>
<eb:To>
<eb:PartyId>xxxxxxxxxxxxxxxxxx</eb:PartyId>
<eb:Role>Receiver</eb:Role>
</eb:To>
<eb:To>
<eb:PartyId>xxxxxxxxxxxxx</eb:PartyId>
<eb:Role>Intermediator</eb:Role>
</eb:To>
<eb:CPAId>yoursandmycpa</eb:CPAId>
<eb:ConversationId>xxxxxxxxxx</eb:ConversationId>
<eb:Service/>
<eb:Action/>
<eb:MessageData>
<eb:MessageId>xxxxxxx</eb:MessageId>
<eb:Timestamp>2016-03-01T10:26:04</eb:Timestamp>
<eb:RefToMessageId/>
</eb:MessageData>
</eb:MessageHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<eb:Manifest eb:id="Manifest" eb:version="2.0">
<eb:Reference eb:id="Invoice" xlink:href="xxxxxx">
<eb:Schema eb:location="Invoice.xsd" eb:version="1.0"/>
</eb:Reference>
</eb:Manifest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<?xml version="1.0" encoding="ISO-8859-15"?>
<?xml-stylesheet type="text/xsl" href="Invoice.xsl"?>
<Invoice Version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Invoice.xsd">
<SellerPartyDetails>
<SellerPartyIdentifier>xxxxxxxxxxxxxxx</SellerPartyIdentifier>
<SellerOrganisationName>xxxxxxxxxxxxxxxxxxxxxxxx</SellerOrganisationName>
<SellerOrganisationTaxCode>xxxxxxxxxxxxx</SellerOrganisationTaxCode>
<SellerPostalAddressDetails>
<SellerStreetName>xxxxxxxxxxxxxxxxxx</SellerStreetName>
<SellerTownName>xxxxxxxxxxxxxxxxxxxxxx</SellerTownName>
<SellerPostCodeIdentifier>xxxxxxxxxxxxxxxxx</SellerPostCodeIdentifier>
</SellerPostalAddressDetails>
</SellerPartyDetails>
</Invoice>
【问题讨论】:
一个 XML 文件必须包含一个单一的根元素。因此,简单的串联不会产生格式良好的 XML 文件。任何 XML 解析器(根据 W3 标准)在收到此类文件时都必须中止并显示错误消息。 是的,这正是我在这里所追求的——格式正确的 XML 文件——目标 XML 格式正确,因为 2 个单独的 xmltype 数据字段包含正确且格式正确的数据(单独)一旦我弄清楚如何将这两者组合成一个元素,它将包含正确的根元素 + 正确的附件作为单个 xml 文件。实际上,我已经接近使用 xmlelement 的最终结果,但是它向根添加了额外的元素,我不能使用它,因为 table1 和 table2 xmltype 记录已经包含正确的根元素。 您是说两个 XMLType 都包含相同的根元素,并且您想将它们的子节点组合在一个根元素下吗?如果您将示例数据添加到问题中 - 在仍然相关的同时尽可能减少 - 以及预期的组合结果,这将非常有帮助。 添加示例数据 你能提供一个期望结果的例子吗? 【参考方案1】:您是否尝试在 PL/SQL 中使用类似的东西:
declare
x varchar(1000);
begin
select column1||' '||column2 ... into x
Where table.id = table2.id
?
【讨论】:
我尝试了这个并得到了这样的错误消息 - 我的 varchar2(32767) 不足以容纳数据.. 19011. 00000 - “字符串缓冲区太小” *原因:要求的字符串结果太大而无法返回 *Action: 以 lob 形式获取结果 该死的,当然。你可以而且你应该使用 CLOB。在 pl/sql 中有一个包 dbms_lob。有很多教程如何使用这个包,这些教程会比我更好地解释这一点。我相信这会解决你的问题:) 正如 Alex Pool 所说 - 注意双根元素。 在程序中可能是这样的?从 xml_table x 中选择 x.OBJECT_VALUE.getCLOBVal();然后我可以将这两个部分添加为变量并将它们组合为 CLOB 并从中创建一个新的 xml 文件?【参考方案2】:我设法通过一个简单的解决方案解决了这个问题:
PROCEDURE PR_COMPILE_DATA_INTO_FILE(
P_TARGET_FOLDER IN VARCHAR2,
P_TARGET_FILENAME IN VARCHAR2,
P_SOAP_CLOB IN CLOB,
P_INVOICE_CLOB IN CLOB
)
AS
V_TEMP CLOB;
BEGIN
dbms_lob.createtemporary(V_TEMP, true);
dbms_lob.append(V_TEMP, P_SOAP_CLOB);
dbms_lob.append(V_TEMP,P_INVOICE_CLOB);
dbms_xslprocessor.clob2file(V_TEMP,P_TARGET_FOLDER,P_TARGET_FILENAME,nls_charset_id('WE8ISO8859P1'));
dbms_lob.freetemporary(V_TEMP);
END PR_COMPILE_DATA_INTO_FILE;
数据是格式正确的xml作为结果文件,一切都完成了。
感谢您对此事的支持和帮助。
【讨论】:
好的,但这是一个包含两个 XML 片段的文本文件,而不是一个 XML 文档。它不是格式良好的 XML。以上是关于将 2 个单独的 XMLType 记录合并到一个 xml 文件中的主要内容,如果未能解决你的问题,请参考以下文章