Oracle Service Bus中含逗号元素的重复结构XML转CSV实现咨询
Oracle Service Bus XML转CSV格式转换实现
需求说明
需要在Oracle Service Bus中完成XML到CSV的格式转换,核心约束如下:
COMPONENT_DESCRIPTION元素本身包含逗号,输出CSV时该字段需要用双引号包裹保证格式正确性P_OUT_PUT_S3_DATA_ITEM为重复元素,每一个节点对应CSV的一行数据
输入XML示例
<P_OUT_PUT_S3_DATA> <P_OUT_PUT_S3_DATA_ITEM> <RECEIPT_DATE>02-APR-21</RECEIPT_DATE> <AWS_ASSET_ID>12345</AWS_ASSET_ID> <RACK_PO_NUMBER>US12345</RACK_PO_NUMBER> <VENDOR_NAME>Foxconn</VENDOR_NAME> <MANUFACTURING_SITE>FOX-SLC</MANUFACTURING_SITE> <COMPONENT_CATEGORY>CPU</COMPONENT_CATEGORY> <COMPONENT_DESCRIPTION>CPU, Intel, Cascade Lake, 8259CL, 24C, 210W</COMPONENT_DESCRIPTION> <APN>1</APN> <COMP_VOL>76</COMP_VOL> </P_OUT_PUT_S3_DATA_ITEM> <P_OUT_PUT_S3_DATA_ITEM> <RECEIPT_DATE>02-APR-21</RECEIPT_DATE> <AWS_ASSET_ID>23456</AWS_ASSET_ID> <RACK_PO_NUMBER>US23456</RACK_PO_NUMBER> <VENDOR_NAME>Foxconn</VENDOR_NAME> <MANUFACTURING_SITE>FOX-SLC</MANUFACTURING_SITE> <COMPONENT_CATEGORY>CPU</COMPONENT_CATEGORY> <COMPONENT_DESCRIPTION>CPU, Intel, Cascade Lake, 8259CL, 24C, 210W</COMPONENT_DESCRIPTION> <APN>1</APN> <COMP_VOL>76</COMP_VOL> </P_OUT_PUT_S3_DATA_ITEM> </P_OUT_PUT_S3_DATA>
预期CSV输出
RECEIPT_DATE,AWS_ASSET_ID,RACK_PO_NUMBER,VENDOR_NAME,MANUFACTURING_SITE,COMPONENT_CATEGORY,COMPONENT_DESCRIPTION,APN,COMP_VOL 02-APR-21,12345,US12345,Foxconn,FOX-SLC,CPU,"CPU, Intel, Cascade Lake, 8259CL, 24C, 210W",1,76 02-APR-21,23456,US23456,Foxconn,FOX-SLC,CPU,"CPU, Intel, Cascade Lake, 8259CL, 24C, 210W",1,76
现有代码问题
原有XSLT代码存在两个核心问题:
- 错误调用
escape-html-uri函数,该函数用于URI转义,完全不符合CSV字段处理需求 - 没有对包含逗号的字段做双引号包裹处理,也未输出CSV表头
修正后XSLT代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <!-- 自定义函数:处理CSV字段,含逗号则用双引号包裹 --> <xsl:function name="local:csv-field"> <xsl:param name="value" as="xs:string"/> <xsl:sequence select=" if (contains($value, ',')) then concat('"', $value, '"') else $value "/> </xsl:function> <xsl:template match="/"> <!-- 输出CSV表头 --> <xsl:text>RECEIPT_DATE,AWS_ASSET_ID,RACK_PO_NUMBER,VENDOR_NAME,MANUFACTURING_SITE,COMPONENT_CATEGORY,COMPONENT_DESCRIPTION,APN,COMP_VOL </xsl:text> <!-- 循环处理每一行数据 --> <xsl:for-each select="P_OUT_PUT_S3_DATA/P_OUT_PUT_S3_DATA_ITEM"> <xsl:value-of select="string-join(( local:csv-field(normalize-space(RECEIPT_DATE)), local:csv-field(normalize-space(AWS_ASSET_ID)), local:csv-field(normalize-space(RACK_PO_NUMBER)), local:csv-field(normalize-space(VENDOR_NAME)), local:csv-field(normalize-space(MANUFACTURING_SITE)), local:csv-field(normalize-space(COMPONENT_CATEGORY)), local:csv-field(normalize-space(COMPONENT_DESCRIPTION)), local:csv-field(normalize-space(APN)), local:csv-field(normalize-space(COMP_VOL)) ), ',')"/> <xsl:text> </xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet>
改动说明
- 新增自定义
local:csv-field函数,自动判断字段值是否包含逗号,包含则自动用双引号包裹,适配CSV格式规范 - 新增表头输出逻辑,符合预期输出要求
- 移除错误的
escape-html-uri调用,替换为适配CSV的字段处理逻辑 - 用更易维护的
xsl:for-each实现循环,逻辑更清晰
内容的提问来源于stack exchange,提问作者Sumir
相关产品推荐
相关产品推荐

