如何获取总元素标签?

How to get total element tag?

提问人:Headshot 提问时间:7/6/2023 最后编辑:Uwe KeimHeadshot 更新时间:7/7/2023 访问量:65

问:

我定义了一些带有一些标签的列表字符串,我想计算每个标签中总共有多少个元素。

<L1 //2 element
 <L1 //1 element
  <H1 content> 
 > 
 <L1 //3 element
  <H2 content> 
  <P content>
  <L1 //1 element
   <H3 content>
  >
 >
>

这是我截取的代码 C#

var str = "<L1\r\n <L1\r\n  <H1 content> \r\n > \r\n <L1\r\n  <H2 content> \r\n  <P content>\r\n  <L1\r\n   <H3 content>\r\n  >\r\n >\r\n>";
var list = str.Split(new string[] { "\r\n" }, StringSplitOptions.None);
var array_num = new List<string>();
int startpos = 0, endpos = 0, total = 0, newstartpos = 0;
bool newtag = false;
for (int i = 0; i < list.Length; i++)
{
    if (list[i].Trim() == "<L1")
    {
        startpos = i;
        for (int Lindex = i + 1; Lindex < list.Length ; Lindex++)
        {
            var item = list[Lindex].Trim().ToString();
            if (list[Lindex].Trim().StartsWith("<L1") && list[Lindex].Trim().EndsWith(">"))
            {
                total += 1;
            }
            if (list[Lindex].Trim() == "<L1")
            {
                total += 2;
                newstartpos = Lindex;
                newtag = true;
            }
            if (list[Lindex].Trim() == ">" && newstartpos != 0)
            {
                total -= 1;
                endpos = Lindex;
                newtag = false;
            }
            if (list[Lindex].Trim().StartsWith("<") && list[Lindex].Trim().EndsWith(">") && !newtag)
            {
                total += 1;
            }
            if (list[Lindex].Trim() == ">" && newstartpos == 0)
            {
                endpos = Lindex;
                break;
            }
        }
        array_num.Add("start: " + startpos + " end: " + endpos + " count: " + total);
        startpos = 0;
        endpos = 0;
        total = 0;
        newstartpos = 0;
        newtag = false;
    }
}

但是当我运行它并得到意想不到的结果时,结果会得到内容。结果是正确的应该是array_num

start:0 end: 11 count: 2 //correct
start:1 end: 3 count: 1 //correct
start:4 end: 11 count: 1 //incorrect should be 4 10 3
start:7 end: 9 count: 1 //correct

但我不确定我的代码是否在其他示例中稳定运行,如果您对此有任何想法或调整某些内容,请让我知道更改的内容。

C C#-4.0 tags 元素

评论

0赞 Peter Dongan 7/6/2023
最好可以将其解析为 XElement 或 XmlNode,但示例中的字符串不会被接受为有效的 XML。
0赞 Headshot 7/6/2023
@Peter,我尝试在上面的代码中找到更多。
0赞 Headshot 7/7/2023
我已经更新了我的代码,但似乎效果不佳

答:

1赞 Peter Dongan 7/7/2023 #1

最好使用堆栈结构,因为它反映了正在分析的内容的结构。

这是一个解决方案。使用堆栈和 TagCounter 类。TagCounter 类跟踪标记的子项数、是否为 L1 标记及其在字符串中的索引,以便它们可以在末尾按正确的顺序排列:

internal class TagCounter
{
    public TagCounter(bool isL1Tag, int index) 
    {
        ChildCount = 0;
        IsL1Tag = isL1Tag;
        Index = index;
    }

    public int ChildCount { get; set; }
    public bool IsL1Tag { get; private set; }
    public int Index { get; set; }
}

代码片段来计算它:

var str = "<L1\r\n <L1\r\n  <H1 content> \r\n > \r\n <L1\r\n  <H2 content> \r\n  <P content>\r\n  <L1\r\n   <H3 content>\r\n  >\r\n >\r\n>";

var openTags = new Stack<TagCounter>();   
var parsedLTags = new List<TagCounter>();

var shortenedString = str.Replace("\r\n", "");
TagCounter? currentTag = null;

var stringLength = shortenedString.Length;

for (var i = 0;i < stringLength; i++)
{
    var nextChar = shortenedString[i];
    if (nextChar == '<')
    {
        if (currentTag != null)
        {
            currentTag.ChildCount++;
        }
       
        var isL1Tag = shortenedString.Substring(i + 1, 2).Equals("L1");
        
        if (currentTag != null)
        {
            openTags.Push(currentTag);
        }
        currentTag = new TagCounter(isL1Tag, i);
    }
    else if (nextChar == '>')
    {
       
        if (currentTag.IsL1Tag)
        {
            parsedLTags.Add(currentTag);
        }

        if (openTags.Any())
        {
            currentTag = openTags.Pop();
        }
        else
        {
            currentTag = null;
        }

    }
}

var result = parsedLTags.OrderBy(x=>x.Index).Select(x=>x.ChildCount).ToList();

评论

0赞 Headshot 7/9/2023
效果很好,最好的答案,tk很多