【问题标题】:Transform string to XML by replacing placeholders with XML elements通过用 XML 元素替换占位符将字符串转换为 XML
【发布时间】:2017-01-24 17:06:18
【问题描述】:

尊敬的 StackOverflow 成员,

我正在使用 C#。我有以下字符串:

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

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

案例一:

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

或 案例二:

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

即同级节点或有子节点的节点。

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

案例一:

<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>

有人对我如何实现这一点有任何提示吗?我已经为此寻找解决方案好几个小时了,但我什至不知道从哪里开始。

提前感谢大家的支持。

问候,

劳伦特

【问题讨论】:

  • 您使用堆栈数据结构的舒适程度如何?
  • 嗨@hoodaticus,我已经使用过堆栈,但我不确定如何在这种特定情况下使用它们。还有一个提示 ;-) ?

标签: c# xml parsing xml-parsing


【解决方案1】:

一般不要尝试使用字符串来操作 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”上,但它显示了这个想法,您应该能够相应地进行调整。

【讨论】:

  • 嗨@JamesT,感谢您的帮助。您的回答使我能够在两种情况下都分配正确的 ID。非常感谢你。我觉得很愚蠢,因为我已经实现了整个逻辑,我唯一缺少的是一个索引,我在处理一个元素后递增。我相信我在这方面工作了太长时间,看不到明显的东西。
  • 不用担心。一双新鲜的眼睛等等。
【解决方案2】:

试试下面的代码。你真的在做事有点倒退。您在字符串之间添加 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]
            });
        }
    }
}

【讨论】:

  • 亲爱的@jdweng,感谢您的解决方案。但是,我选择了 JamesT 的解决方案,因为我遵循相同的逻辑但出于其他目的。感谢您提供帮助。
猜你喜欢
  • 2013-04-03
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2018-08-29
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
相关资源
最近更新 更多