如何在C#中将*.RESX XML文件转换为JSON文件

10

我怎样能在C#中将*.RESX XML文件转换为JSON文件?

我有一个普通的RESX文件,例如:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" use="required" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
    <data xml:space="preserve" name="KEY_1">       
        <value>Text A</value>
    </data>
    <data xml:space="preserve" name="KEY_2">       
        <value>Text B</value>
    </data>
</root>

我需要将这个文件转换为 JSON 文件:

{
  "Texts": [
    {
      "id": "KEY_1",
      "text": "Text A"
    },
    {
      "id": "KEY_2",
      "text": "Text B"
    }
  ]
}

正如你所看到的,转换只涉及数据部分:

    <data xml:space="preserve" name="KEY_1">       
        <value>Text A</value>
    </data>
    <data xml:space="preserve" name="KEY_2">       
        <value>Text B</value>
    </data>

除了变换外,其他都是无关紧要的。

  1. 数据属性XML中的名称 => 在JSON文件中是id
  2. XML中的值 => 在JSON文件中是text

编辑: 我有解决方案,但我认为它可以做得更好。

using System.Xml;
using System.IO;
using System.Collections.Generic;
using System.Linq;

namespace XMLtoJSON
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();
            // To convert an XML node contained in string xml into a JSON string 
            var xml = File.ReadAllText(@"C:\Test\ClientLocalization.en-US.resx");
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            XmlNodeList node = doc.GetElementsByTagName("data");
            foreach (XmlNode item in node)
            {
                var value = item.InnerText.Trim();
                var keyName = item.Attributes.Cast<XmlAttribute>().FirstOrDefault(f => f.Name == "name");
                if (keyName != null)
                {
                    var key = keyName.InnerText.Trim();
                    result.Add(key, value);
                }
            }

            string res = @"{ ""Text"" : [ ";
            foreach (var item in result)
            {
                res += "{";
                res += $" \"id\":\"{item.Key}\",\"text\":\"{item.Value}\"";
                res += "},";
            }
            res = res.Remove(res.Length - 1);
            res += @" ]} ";
        }

    }
}

不幸的是,这是一个非常不紧凑的JSON格式...在npm中有一个将resx转换为json的工具,它可以生成更加紧凑的JSON格式。类似于{"KEY_1":"Text A","KEY_2":"Text B"}这样的结构在JavaScript世界中更受欢迎... - enorl76
2个回答

14

不要使用XmlDocument,而是使用XElement,因为它更适合使用LINQ。使用XElement.Parse加载XML,然后选择您感兴趣的节点并将它们塑造成一个匿名对象结构,该结构镜像了您想要的JSON。最后,使用您喜爱的JSON序列化程序(例如Json.NetJavaScriptSerializer)从中创建JSON。我不建议手动编写自己的JSON,因为这很容易出错。

using Newtonsoft.Json;

var xml = File.ReadAllText(@"C:\Test\ClientLocalization.en-US.resx");

var obj = new
{
    Texts = XElement.Parse(xml)
        .Elements("data")
        .Select(el => new
        {
            id = el.Attribute("name").Value,
            text = el.Element("value").Value.Trim()
        })
        .ToList()
};

string json = JsonConvert.SerializeObject(obj, Newtonsoft.Json.Formatting.Indented);

// OR:
//JavaScriptSerializer jss = new JavaScriptSerializer();
//string json = jss.Serialize(obj);

Console.WriteLine(json);

Fiddle:https://dotnetfiddle.net/ZIaCjd


非常非常好 :) - Raskolnikov

3
我建议您使用JSON.NET框架。 它内置了将XML转换为JSON和将JSON转换为XML的函数。
示例:
string xml = @"<?xml version='1.0' standalone='no'?>
<root>
  <person id='1'>
    <name>Alan</name>
    <url>http://www.google.com</url>
  </person>
  <person id='2'>
    <name>Louis</name>
    <url>http://www.yahoo.com</url>
  </person>
</root>";

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

string jsonText = JsonConvert.SerializeXmlNode(doc);
//{
//  "?xml": {
//    "@version": "1.0",
//    "@standalone": "no"
//  },
//  "root": {
//    "person": [
//      {
//        "@id": "1",
//        "name": "Alan",
//        "url": "http://www.google.com"
//      },
//      {
//        "@id": "2",
//        "name": "Louis",
//        "url": "http://www.yahoo.com"
//      }
//    ]
//  }
//}

2
虽然Json.Net确实有能力使用SerializeXmlNode直接将XML转换为JSON,但对于这种特定情况并不适用。在这种情况下,OP只想要原始XML的子集,并希望将name属性和value元素重命名为idtext。此外,他希望数据行在JSON中显示为Texts数组,而在XML中没有相应的元素。SerializeXmlNode不提供自定义其行为的方法,因此OP需要预处理XML以使其首先达到正确的形状。 - Brian Rogers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接