【问题标题】:C# XML tags to csvC# XML 标记到 csv
【发布时间】:2019-03-05 09:17:21
【问题描述】:

我有十几个以下列格式提交的 XML(简短示例):

<namespace name="Colors">
    <green>
        <en>Green</en>
        <de>Gruen</de>
    </green>
    <blue>
        <en>Blue</en>
        <de>Blau</de>
    </blue>
    <namespace name="Subcolors">
        <perlwhite>
            <en>Perl White</en>
            <de>Perlweis</de>
        </perlwhite>
        <racingblack>
            <en>Racing Black</en>
            <de>Rennschwarz</de>
        </racingblack>
    </namespace>
</namespace>

我必须提取所有语言标签并以这种格式将它们输出到 csv 文件中:

en;de;
Green;Gruen;
Blue;Blau;
Perl White;Perlweiß;
Racing Black;Renn Schwarz;

然后,我把这个 CSV 文件交给翻译。翻译后,CSV 文件中添加了一种新语言,例如法语:

en;de;fr;
Green;Gruen;Vert;
Blue;Blau;Bleu;
Perl White;Perlweiß;Perl Blanc;
Racing Black;Rennschwarz;Courses Noir;

然后我需要再次读取这个 csv 文件,并将所有标签附加到所有相应的 xml 文件中,如下所示:

<namespace name="Colors">
    <green>
        <en>Green</en>
        <de>Gruen</de>
        <fr>Vert</fr>
    </green>
    <blue>
        <en>Blue</en>
        <de>Blau</de>
        <fr>Bleu</fr>
    </blue>
    <namespace name="Subcolors">
        <perlwhite>
            <en>Perl White</en>
            <de>Perlweis</de>
            <fr>Perl Blanc</fr>
        </perlwhite>
        <racingblack>
            <en>Racing Black</en>
            <de>Renn Schwarz</de>
            <fr>Courses Noir</fr>
        </racingblack>
    </namespace>
</namespace>

命名空间或其他节点(此处未列出,如“多色”、“彩色”等)可以嵌套多次。并非每个文件都包含每个节点。并不是每个节点都以相同的方式嵌套在每个 xml 文件中。这因文件而异。但最后,每个分支都以几个语言标签结束。这些需要阅读和更新。

所以一个 xml 文件可以是这样的:

<namespace name="Colors">
    <green>
        <en>Green</en>
        <de>Gruen</de>
    </green>
    <blue>
        <en>Blue</en>
        <de>Blau</de>
    </blue>
        <namespace name="Subcolors">
            <perlwhite>
                <en>Perl White</en>
                <de>Perlweis</de>
            </perlwhite>
            <racingblack>
                <en>Racing Black</en>
                <de>Rennschwarz</de>
            </racingblack>
            <colored>
                <namespace name="Misc">
                    <fruits>
                        <apple>
                            <de>Apfel</de>
                            <en>Apple</en>
                        </apple>
                        <orange>
                            <de>Orange</de>
                            <en>Orange</en>
                        </orange>
                    </fruits>
                    <vegetables>
                        <cucumber>
                            <en>Cucumber</en>
                            <de>Gurke</de>
                        </cucumber>
                    </vegetables>
                    <namespace name="Other">
                        <othertag>
                            <entry>
                                <en>Entry</en>
                                <de>Eintrag</de>
                            </entry>
                        </othertag>
                    </namespace>
                </namespace>
            </colored>
        </namespace>
    </namespace>

所以不是每个xml文件都是一样的,不同的节点有不同的标签名,不同的嵌套。但是每个分支都以语言标签结尾。

有人可以帮助我用 C# 以简单的方式做到这一点吗?可能有两个简单的函数,比如 Import(readCsvPath, appendXmlPath) 和 Export(readXmLPath, writeCsvPath)。

【问题讨论】:

  • 为版主的利益发表评论,这对我来说就像一个家庭作业问题
  • @Horst 你在这方面做过什么尝试吗?如果是这样,您能否将其包含在内,以便我们查看可能出现的问题?其中哪一部分您需要帮助?

标签: c# xml csv


【解决方案1】:

代码基本上可以解决问题。原来的 xml 有 perlwhite,但新的 csv 有 Perl-White。你怎么知道把破折号放在哪里。我将小 p 转换为大 P 但不知道在哪里放置破折号。

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

namespace ConsoleApplication103
{
    class Program
    {
        const string INPUT_XML = @"c:\temp\test.xml";
        const string OUTPUT_CSV = @"c:\temp\test.csv";
        const string INPUT_CSV = @"c:\temp\test2.csv";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(INPUT_XML);

            var colorsWithDuplicates = doc.Descendants("namespace")
                .SelectMany(ns => ns.Elements()
                .SelectMany(color => color.Elements().Select(y => new {color = color.Name.LocalName,  language = y.Name.LocalName, value = (string)y}))
                ).ToList();

            var colors = colorsWithDuplicates.GroupBy(x => new object[] { x.color, x.language }).Select(x => x.First()).ToList();

            var sortedAndGrouped = colors.OrderBy(x => x.language).ThenBy(x => x.color).GroupBy(x => x.color).ToList();

            List<string> countries = sortedAndGrouped.FirstOrDefault().Select(x => x.language).ToList();

            StreamWriter writer = new StreamWriter(OUTPUT_CSV, false, Encoding.Unicode);
            writer.WriteLine(string.Join(",",countries));

            foreach (var color in sortedAndGrouped)
            {
                writer.WriteLine(string.Join(";",color.Select(x => x.value)));
            }
            writer.Flush();
            writer.Close();

            StreamReader reader = new StreamReader(INPUT_CSV);

            List<string> newCountries = reader.ReadLine().Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            string line = "";
            Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();
            while ((line = reader.ReadLine()) != null)
            {
                line = line.Trim();
                List<string> splitLine = line.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                dict.Add(splitLine[0], splitLine);
            }

            //now replace colors
            foreach (XElement xNs in doc.Descendants("namespace"))
            {
                string name = (string)xNs.Attribute("name");
                if((name == "Colors") || (name == "Subcolors"))
                {
                    foreach (XElement xColor in xNs.Elements())
                    {
                        if (xColor.Name.LocalName != "namespace")
                        {

                            string checkColor = xColor.Name.LocalName;
                            checkColor = (string)xColor.Element("en");  // use english name
                            if (checkColor != null)
                            {
                                List<string> inputColors = dict[checkColor];
                                for (int index = 0; index < inputColors.Count; index++)
                                {
                                    XElement country = xColor.Element(newCountries[index]);
                                    if (country == null)
                                    {
                                        xColor.Add(new XElement(newCountries[index], inputColors[index]));
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    foreach (XElement group in xNs.Elements())
                    {
                        foreach(XElement xColor in group.Elements())
                        {

                            string checkColor = xColor.Name.LocalName;
                            checkColor = char.ToUpper(checkColor[0]) + checkColor.Substring(1);
                            if (checkColor != null)
                            {
                                List<string> inputColors = dict[checkColor];
                                for (int index = 0; index < inputColors.Count; index++)
                                {
                                    XElement country = xColor.Element(newCountries[index]);
                                    if (country == null)
                                    {
                                        xColor.Add(new XElement(newCountries[index], inputColors[index]));
                                    }
                                }
                            }
                        }
                    }
                }
            }

        }
    }


}

【讨论】:

  • 抱歉,这只是一个错字。两个文件(en 和 de)中的条目是相同的。而在翻译处发回的文件中,又添加了一种语言。我需要将这种语言添加到 xml 文件中吗?
  • 代码应将所有新语言添加到 xml。我只是没有在代码末尾保存文档。该代码只会更改原始 xml 文件中的颜色。不添加任何新颜色或子颜色。
  • 不幸的是,此代码不适用于“更深”的嵌套标签。标签可以以不同的方式嵌套。 (我已经编辑了第一篇文章以使其更加清晰。)所以这对我来说是困难的部分,因为它不能被硬编码,因为不同的 xml 标签“深度”。
  • 可以让xml更加一致吗?对于命名空间 Colors 和 SubColors,颜色是子级。对于所有其他名称空间,颜色是孙子。我可以通过处理与其他命名空间不同的颜色和子颜色来处理,但如果 xml 更一致就更好了。
  • 你的颜色苹果、橙、黄瓜和入口在哪里?
【解决方案2】:

对于将 XML 导入 CSV 文件,您可以使用以下代码,这并不长且容易:

XmlDocument xml = new XmlDocument();
// xmlContent contains your XML file
xml.LoadXml(xmlContent);
// get collections of nodes representing translations in particular languages
var enNodes = xml.GetElementsByTagName("en");
var deNodes = xml.GetElementsByTagName("de");

string[] lines = new string[enNodes.Count];
for (int i = 0; i < enNodes.Count; i++)
    lines[i] = $"{enNodes[i].InnerText},{deNodes[i].InnerText}";
File.WriteAllLines(@"path to text file", lines);

另一方面,CSV 到 XML 需要更多的编码,因为您必须检测每个节点以进行翻译并添加另一个代表新语言的节点。这需要更多的编码并且对于答案来说过于宽泛 - 您必须先自己编写一些代码,然后再针对您可能遇到的问题提出更准确的问题。

祝你好运。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-05
    • 2015-09-15
    • 1970-01-01
    相关资源
    最近更新 更多