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

XSLT全局变量使用问题:JSON转XML行级元素未填充

解决XSLT JSON转XML中订单级变量无法在行级for-each填充的问题

问题本质

XSLT的变量是作用域绑定的,你遇到的问题大概率是两个原因:要么是订单级变量定义时没正确捕获订单节点的上下文,要么是json-to-xml()转换后的节点路径写错了,导致变量本身就是空值,自然在行级for-each里输出不了内容。另外,如果你用的是旧版XSLT处理器,也可能存在JSON处理的兼容性问题。

示例代码分析

先假设你的原始JSON和出错的XSLT是这样的(如果和你的实际代码不符,可以对照调整):

示例JSON

{
  "Order": {
    "OrderID": "ORD001",
    "Customer": "Alice",
    "Lines": [
      {"LineID": "L001", "Product": "Book"},
      {"LineID": "L002", "Product": "Pen"}
    ]
  }
}

出错的XSLT(常见错误写法)

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <Root>
      <xsl:apply-templates select="json-to-xml(.)/*[@key='Order']"/>
    </Root>
  </xsl:template>

  <xsl:template match="*[@key='Order']">
    <!-- 定义订单级变量 -->
    <xsl:variable name="orderID" select="*[@key='OrderID']/text()"/>
    <xsl:variable name="customer" select="*[@key='Customer']/text()"/>
    <Order>
      <OrderID><xsl:value-of select="$orderID"/></OrderID>
      <Customer><xsl:value-of select="$customer"/></Customer>
      <!-- 行级循环 -->
      <xsl:for-each select="*[@key='Lines']/*">
        <Line>
          <LineID><xsl:value-of select="*[@key='LineID']/text()"/></LineID>
          <Product><xsl:value-of select="*[@key='Product']/text()"/></Product>
          <!-- 这里输出为空 -->
          <OrderRef><xsl:value-of select="$orderID"/></OrderRef>
          <CustomerRef><xsl:value-of select="$customer"/></CustomerRef>
        </Line>
      </xsl:for-each>
    </Order>
  </xsl:template>
</xsl:stylesheet>

这个写法的问题:json-to-xml()转换后的节点,文本内容直接在元素里,不需要加/text(),而且如果循环时上下文切换后,变量本身可能因为路径错误是空的,或者你没正确保存订单节点的上下文。

解决办法

办法1:正确绑定订单节点上下文(基于XML节点处理)

先把整个订单节点保存到变量里,后续不管上下文怎么切换,都通过这个变量访问订单级数据,同时修正节点选择路径:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <Root>
      <xsl:apply-templates select="json-to-xml(.)/*[@key='Order']"/>
    </Root>
  </xsl:template>

  <xsl:template match="*[@key='Order']">
    <!-- 保存当前订单节点的上下文 -->
    <xsl:variable name="orderNode" select="."/>
    <Order>
      <OrderID><xsl:value-of select="$orderNode/*[@key='OrderID']"/></OrderID>
      <Customer><xsl:value-of select="$orderNode/*[@key='Customer']"/></Customer>
      <!-- 通过保存的orderNode定位行数据 -->
      <xsl:for-each select="$orderNode/*[@key='Lines']/*">
        <Line>
          <LineID><xsl:value-of select="*[@key='LineID']"/></LineID>
          <Product><xsl:value-of select="*[@key='Product']"/></Product>
          <!-- 直接通过orderNode访问订单级数据 -->
          <OrderRef><xsl:value-of select="$orderNode/*[@key='OrderID']"/></OrderRef>
          <CustomerRef><xsl:value-of select="$orderNode/*[@key='Customer']"/></CustomerRef>
        </Line>
      </xsl:for-each>
    </Order>
  </xsl:template>
</xsl:stylesheet>

办法2:直接操作JSON对象(XSLT 3.0推荐写法)

不用把JSON转成XML节点,直接用parse-json()解析成map/array,操作更直观,也不会有上下文切换的问题:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <!-- 解析JSON为map对象 -->
    <xsl:variable name="jsonData" select="parse-json(.)"/>
    <Root>
      <Order>
        <OrderID><xsl:value-of select="$jsonData?Order?OrderID"/></OrderID>
        <Customer><xsl:value-of select="$jsonData?Order?Customer"/></Customer>
        <!-- 遍历订单的Lines数组 -->
        <xsl:for-each select="$jsonData?Order?Lines?*">
          <Line>
            <LineID><xsl:value-of select="?LineID"/></LineID>
            <Product><xsl:value-of select="?Product"/></Product>
            <!-- 直接访问外层的订单数据 -->
            <OrderRef><xsl:value-of select="$jsonData?Order?OrderID"/></OrderRef>
            <CustomerRef><xsl:value-of select="$jsonData?Order?Customer"/></CustomerRef>
          </Line>
        </xsl:for-each>
      </Order>
    </Root>
  </xsl:template>
</xsl:stylesheet>

额外检查项

  • 先用json-to-xml(.)输出转换后的XML结构,确认节点的@key属性和你写的选择器完全匹配,比如有没有大小写错误。
  • 确保你用的是支持XSLT 3.0的处理器(比如Saxon HE/PE),旧版处理器对JSON的支持有限。
  • 变量要定义在for-each循环之前的作用域里,确保循环内可以访问。

内容的提问来源于stack exchange,提问作者ChrisP

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 20:35:24