如何在XSLT转换JSON到XML时显示Client等父节点?
问题
使用XSLT将JSON转换为XML时,输出仅包含子节点(如Date、Lang),但Client、ClientApp、Payment、Bill这些父节点未出现在结果中,请问模板缺少什么配置才能让这些父节点显示?
原始模板
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xj="http://camel.apache.org/component/xj" exclude-result-prefixes="xj"> <xsl:output omit-xml-declaration="no" encoding="UTF-8" method="xml" indent="yes"/> <xsl:template match="/"> <xsl:apply-templates select="//object"/> </xsl:template> <xsl:template match="object[@xj:type != 'object' and @xj:type != 'array' and string-length(@xj:name) > 0]"> <xsl:variable name="name" select="@xj:name"/> <xsl:element name="{$name}"> <xsl:value-of select="text()"/> </xsl:element> </xsl:template> <xsl:template match="@*|node()"/> </xsl:stylesheet>
输入JSON
{ "Client": { "Date": "2022-12-29T09:55:05", "Lang": "es-CO", "ClientApp": { "Org": "COMPANY", "Name": "NAME COMPANY", "Version": 1 } }, "Payment": { "PaymentId": "00000000-0000-0000-0000-943534532", "Bill": { "PaymentId": "00000000-0000-0000-0000-943534532", "PaymeentNumber": 63703, "BillId": "00000000-0000-0000-0000-003223439138" } } }
当前输出XML
<?xml version="1.0" encoding="UTF-8"?> <Date>2022-12-29T09:55:05</Date> <Lang>es-CO</Lang> <Org>COMPANY</Org> <Name>NAME COMPANY</Name> <Version>1</Version> <PaymentId>00000000-0000-0000-0000-943534532</PaymentId> <PaymentId>00000000-0000-0000-0000-943534532</PaymentId> <PaymeentNumber>63703</PaymeentNumber> <BillId>00000000-0000-0000-0000-003223439138</BillId>
Camel XJ转换后的中间XML输入
<?xml version="1.0" encoding="UTF-8"?> <object xmlns:xj="http://camel.apache.org/component/xj" xj:type="object"> <object xj:name="Client" xj:type="object"> <object xj:name="Date" xj:type="string">2022-12-29T09:55:05</object> <object xj:name="Lang" xj:type="string">es-CO</object> <object xj:name="ClientApp" xj:type="object"> <object xj:name="Org" xj:type="string">COMPANY</object> <object xj:name="Name" xj:type="string">NAME COMPANY</object> <object xj:name="Version" xj:type="int">1</object> </object> </object> <object xj:name="Payment" xj:type="object"> <object xj:name="PaymentId" xj:type="string">00000000-0000-0000-0000-943534532</object> <object xj:name="Bill" xj:type="object"> <object xj:name="PaymentId" xj:type="string">00000000-0000-0000-0000-943534532</object> <object xj:name="PaymeentNumber" xj:type="int">63703</object> <object xj:name="BillId" xj:type="string">00000000-0000-0000-0000-003223439138</object> </object> </object>
问题原因
你的模板只处理了非object/array类型的object节点(也就是叶子节点),而那些类型为object的父节点(如Client、ClientApp)既没有匹配到专门的模板,又被最后那个空模板<xsl:template match="@*|node()"/>拦截,导致它们不会生成对应的XML元素,也不会递归处理子节点。
修改后的XSLT模板
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xj="http://camel.apache.org/component/xj" exclude-result-prefixes="xj"> <xsl:output omit-xml-declaration="no" encoding="UTF-8" method="xml" indent="yes"/> <!-- 处理根节点,只应用模板到根节点下的子object节点(避免处理无名称的根object) --> <xsl:template match="/"> <xsl:apply-templates select="/object/object"/> </xsl:template> <!-- 处理类型为object且有名称的节点,生成对应元素并递归处理子节点 --> <xsl:template match="object[@xj:type='object' and string-length(@xj:name) > 0]"> <xsl:variable name="name" select="@xj:name"/> <xsl:element name="{$name}"> <xsl:apply-templates select="object"/> </xsl:element> </xsl:template> <!-- 处理值类型的节点(string/int等),生成对应元素并输出文本 --> <xsl:template match="object[@xj:type != 'object' and @xj:type != 'array' and string-length(@xj:name) > 0]"> <xsl:variable name="name" select="@xj:name"/> <xsl:element name="{$name}"> <xsl:value-of select="text()"/> </xsl:element> </xsl:template> <!-- 空模板,拦截未匹配的节点(如无名称的根object) --> <xsl:template match="@*|node()"/> </xsl:stylesheet>
修改说明
- 新增object类型节点的处理模板:针对
xj:type='object'且有名称的节点,生成对应名称的XML元素,并递归处理其内部的子object节点,这样父节点会被保留,同时子节点也能正常生成。 - 调整根模板的选择范围:从
//object改为/object/object,避免处理没有xj:name的根节点,防止生成多余的空元素。 - 保留原有值类型节点的处理逻辑:确保叶子节点的文本值正常输出。
预期输出XML
<?xml version="1.0" encoding="UTF-8"?> <Client> <Date>2022-12-29T09:55:05</Date> <Lang>es-CO</Lang> <ClientApp> <Org>COMPANY</Org> <Name>NAME COMPANY</Name> <Version>1</Version> </ClientApp> </Client> <Payment> <PaymentId>00000000-0000-0000-0000-943534532</PaymentId> <Bill> <PaymentId>00000000-0000-0000-0000-943534532</PaymentId> <PaymeentNumber>63703</PaymeentNumber> <BillId>00000000-0000-0000-0000-003223439138</BillId> </Bill> </Payment>
内容的提问来源于stack exchange,提问作者scafrs
相关产品推荐
相关产品推荐

