将 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 文件中的主要内容,如果未能解决你的问题,请参考以下文章

oracle, xmltype/clob substr 循环

将多个项目合并到一个解决方案中,同时保留 git 历史记录

如何将两个单独的 javascript 合并为一个?

将多个库模块合并为一个

node.js:并排合并 2 个图像并将其保存回来

如何将2条提升曲线的图形合并到Python中的单个图形中