You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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>
修改说明
  1. 新增object类型节点的处理模板:针对xj:type='object'且有名称的节点,生成对应名称的XML元素,并递归处理其内部的子object节点,这样父节点会被保留,同时子节点也能正常生成。
  2. 调整根模板的选择范围:从//object改为/object/object,避免处理没有xj:name的根节点,防止生成多余的空元素。
  3. 保留原有值类型节点的处理逻辑:确保叶子节点的文本值正常输出。
预期输出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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 13:21:28