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

Elixir中XML转JSON问题:Sweetyxml及xmerl解析未得到预期结果

实现步骤

你需要先在项目中引入JSON序列化依赖,在mix.exs的deps配置中添加:

defp deps do
  [
    {:jason, "~> 1.4"}
  ]
end

执行mix deps.get安装依赖后,使用如下完整代码即可完成转换:

defmodule XmlToJson do
  # 提取XML节点文本内容
  defp get_node_text([]), do: ""
  defp get_node_text([{:xmlText, _, _, _, text, :text} | _]) do
    to_string(text) |> String.trim()
  end
  defp get_node_text([_ | rest]), do: get_node_text(rest)

  # 类型转换:把文本值转为对应JSON类型
  defp convert_type(""), do: ""
  defp convert_type("true"), do: true
  defp convert_type("false"), do: false
  defp convert_type(val) do
    cond do
      String.match?(val, ~r/^\d+$/) -> String.to_integer(val)
      String.match?(val, ~r/^\d+\.\d+$/) -> 
        num = String.to_float(val)
        if num == trunc(num), do: trunc(num), else: num
      true -> val
    end
  end

  def run(file_path) do
    # 读取解析XML
    {:ok, xmldoc} = File.read(Path.expand(file_path))
    {doc, []} = xmldoc |> to_charlist() |> :xmerl_scan.string()

    # 提取order节点下所有子节点
    order_fields = 
      for element <- doc.content, 
          match?({:xmlElement, _, _, _, _, _, _, _, _, _, _, _}, element) do
        key = element.name |> to_string()
        value = element.content |> get_node_text() |> convert_type()
        {key, value}
      end
      |> Map.new()

    # 生成目标结构并转JSON
    %{"order" => order_fields}
    |> Jason.encode!(pretty: true)
  end
end

# 调用示例
XmlToJson.run("/Users/sohaibanwar/Desktop/unconfirmed_order.xml") |> IO.puts()

逻辑说明

  1. 针对:xmerl_scan返回的标准XML节点结构,编写了专门的文本提取函数,自动处理空标签、嵌套内容的场景
  2. 类型转换函数会自动识别布尔值、整数、浮点数,其中.00结尾的浮点数会自动转为整数,完全匹配要求的JSON格式
  3. 最终输出开启了pretty: true参数,会直接生成格式化后的JSON字符串

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 17:27:02