使用XSLT 1.0为XML添加父节点解决文档良构报错问题
问题原因
标准XML语法强制要求单个文档有且仅有一个顶层根元素,当前收到的内容在XML声明后并列存在<SARIETransferRq>、<Signature>两个同级顶层节点,不符合良构要求,传入XSLT处理器时就会触发根元素之后的文档标记必须符合良构规范的报错。只要给所有顶层节点套一层统一的父根节点就能彻底解决问题。
可行实现方案
最稳定、兼容性最好的方式是在将内容传入XSLT处理器前做一层轻量预处理,不需要改动原有业务节点的任何内容、结构、缩进,实现逻辑非常简单:
- 第一步:提取原始内容开头的XML声明段:
<?xml version="1.0" encoding="UTF-8" ?> - 第二步:在XML声明后拼接自定义根节点的起始标签
<SampleRoot> - 第三步:原封不动拼接XML声明之后的所有原始业务内容
- 第四步:在内容末尾拼接根节点的闭合标签
</SampleRoot>,就能得到符合要求的良构XML。
如果担心纯字符串拼接的容错问题,也可以用支持XML片段解析的工具读取原始内容:先手动创建<SampleRoot>作为根节点,再把解析得到的两个原始顶层节点(SARIETransferRq、Signature)作为子节点挂到根节点下,最后序列化输出即可,全程不会修改原始业务字段的任何值。
不推荐依赖XSLT引擎的非标准配置直接解析多根内容,不同版本、不同厂商的XSLT处理器对非良构XML的兼容逻辑差异很大,生产环境容易出现偶发解析失败的问题。
原始待处理XML结构
<?xml version="1.0" encoding="UTF-8" ?> <SARIETransferRq> <SARIETransferRqHeader> <CorporateID>Sample123</CorporateID> <CorpReferenceNumber>Sample123</CorpReferenceNumber> </SARIETransferRqHeader> <SARIETransferRqBody> <AccountNumber>0000111111111222222</AccountNumber> <DebitCurrency>SAR</DebitCurrency> <TransferAmount>12</TransferAmount> <TransferCurrency>SAR</TransferCurrency> <BeneficiaryName>SAMPLE NAME</BeneficiaryName> <BeneficiaryAccountNumber>Sample1231111111</BeneficiaryAccountNumber> <BeneficiaryAddress1>733r</BeneficiaryAddress1> <BeneficiaryAddress2>6Sample123y</BeneficiaryAddress2> <BeneficiaryAddress3>1Sample123ver</BeneficiaryAddress3> <BankBIC>AAAAAA</BankBIC> <PaymentDate>2021-02-24</PaymentDate> <Instructions1>qewerr</Instructions1> <Instructions2>luaba</Instructions2> <Instructions3>fadjiugu</Instructions3> <Instructions4>rifdij</Instructions4> <Description>sample description for service fee</Description> <AMLPurposeCode>BB</AMLPurposeCode> </SARIETransferRqBody> </SARIETransferRq> <Signature> <SignatureValue>sample</SignatureValue> </Signature>
期望输出的良构XML结构
<?xml version="1.0" encoding="UTF-8" ?> <SampleRoot> <SARIETransferRq> <SARIETransferRqHeader> <CorporateID>Sample123</CorporateID> <CorpReferenceNumber>Sample123</CorpReferenceNumber> </SARIETransferRqHeader> <SARIETransferRqBody> <AccountNumber>0000111111111222222</AccountNumber> <DebitCurrency>SAR</DebitCurrency> <TransferAmount>12</TransferAmount> <TransferCurrency>SAR</TransferCurrency> <BeneficiaryName>SAMPLE NAME</BeneficiaryName> <BeneficiaryAccountNumber>Sample1231111111</BeneficiaryAccountNumber> <BeneficiaryAddress1>733r</BeneficiaryAddress1> <BeneficiaryAddress2>6Sample123y</BeneficiaryAddress2> <BeneficiaryAddress3>1Sample123ver</BeneficiaryAddress3> <BankBIC>AAAAAA</BankBIC> <PaymentDate>2021-02-24</PaymentDate> <Instructions1>qewerr</Instructions1> <Instructions2>luaba</Instructions2> <Instructions3>fadjiugu</Instructions3> <Instructions4>rifdij</Instructions4> <Description>sample description for service fee</Description> <AMLPurposeCode>BB</AMLPurposeCode> </SARIETransferRqBody> </SARIETransferRq> <Signature> <SignatureValue>sample</SignatureValue> </Signature> </SampleRoot>
内容的提问来源于stack exchange,提问作者Varaprasad Bolisetty
相关产品推荐
相关产品推荐

