通过用XML元素替换占位符将字符串转换为XML

时间:2017-01-24 17:06:18

标签: c# xml parsing xml-parsing

亲爱的StackOverflow成员,

我在C#工作。我有以下字符串:

"This {1} is {2}really{3} great {4}, isn't it?"

大括号之间的占位符可能对应于以下标记(包含在数组中):

案例1:

{1} = <cf underline="single">
{2} = <cf bold="True">
{3} = </cf>
{4} = </cf>

或 案例2:

{1} = <cf underline="single">
{2} = </cf>
{3} = <cf bold="True">
{4} = </cf>

即。同一级别的节点或带有子节点的节点。

我想在我的段中插入标记,这可以通过在我的数组中循环并使用指定的值替换相应的占位符来轻松完成。这是容易的部分。 但是,我想在begin元素中插入一个属性,该属性将包含开头的ID和结束标记,以便我的XML看起来像这样:

案例1:

<seg>
 This
  <cf underline="single" startID=1 endId=4>
   is 
    <cf bold="True" startID=2 endId=3>
     really
    </cf>
     great 
  </cf>
 , isn't it?"
</seg>

案例2:

<seg>
 This
  <cf underline="single" startID=1 endId=2>
   is 
  </cf>
  really
  <cf bold="True" startID=3 endId=4>
   great 
  </cf>
 , isn't it?"
</seg>

有没有人提示我如何实现这一目标?我一直在寻找一个解决方案好几个小时,但我甚至不知道我可以从哪里开始。

我事先感谢你们的支持。

此致

劳伦

2 个答案:

答案 0 :(得分:0)

通常不要尝试使用字符串操作Xml。这是一个令人头痛的问题,在你做对了之前你会多次搞砸它。使用XmlDocument。

对于您的模板替换,您可以使用字符串。然后,我建议将其转换为xml文档,然后向下走,以便在之后设置属性。

这样的事情:

using System;
using System.Xml;

public class Program
{


    public static void WalkXml(XmlElement node, ref int index) {

        node.SetAttribute("startIndex", index.ToString());

        foreach(XmlNode child in node.ChildNodes) {
            XmlElement element = (child as XmlElement);
            if (element != null) {
                index++;
                WalkXml(element, ref index);
            }

        }
        node.SetAttribute("endIndex", (++index).ToString());
    }

    public static void WriteXml(string message, string[] tags) {
        var xmlStr = $"<seg>{String.Format(message, tags)}</seg>";
        var xmlObj = new XmlDocument();
        xmlObj.LoadXml(xmlStr);

        int index = 1;
        WalkXml(xmlObj.DocumentElement, ref index);     

        Console.WriteLine(xmlObj.InnerXml);
    }

    public static void Main()
    {
        string[] tags1 = new string[] {
            "<cf underline=\"single\">",
            "<cf bold=\"True\">",
            "</cf>",
            "</cf>"
        };

        string[] tags2 = new string[] {
            "<cf underline=\"single\">",
            "</cf>",
            "<cf bold=\"True\">",
            "</cf>"
        };      

        string message = "This {0} is {1}really{2} great {3}, isn't it?";

        WriteXml(message, tags1);
        WriteXml(message, tags2);
    }

}

这是输出

<seg startIndex="1" endIndex="6">This <cf underline="single" startIndex="2" endIndex="5"> is <cf bold="True" startIndex="3" endIndex="4">really</cf> great </cf>, isn't it?</seg>
<seg startIndex="1" endIndex="6">This <cf underline="single" startIndex="2" endIndex="3"> is </cf>really<cf bold="True" startIndex="4" endIndex="5"> great </cf>, isn't it?</seg>

演示代码也将索引放在“seg”上,但它显示了这个想法,你应该能够相应地进行调整。

答案 1 :(得分:0)

请尝试以下代码。你真的做了一些倒退的事情。您正在字符串之间添加xml,而不是将字符串添加到xml中。

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

namespace ConsoleApplication43
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] input = { "This", "is","really", "great",", isn't it?"};
            KeyValuePair<int, int>[] startEndId = {
                new KeyValuePair<int,int>(1,4),
                new KeyValuePair<int,int>(2,3)
            };


            var seq = new XElement("seg", new object[] {
                input[0],
                new XElement("cf", new object[] {
                    new XAttribute("underline", "single"),
                    new XAttribute("startID", startEndId[0].Key),
                    new XAttribute("endID", startEndId[0].Value),
                    input[1],
                    new XElement("cf", new object[] {
                        new XAttribute("bold", "True"),
                        new XAttribute("startID", startEndId[1].Key),
                        new XAttribute("endID", startEndId[1].Value),
                        input[2],
                    }),
                    input[3],
                }),
                input[4]
            });
        }
    }
}