.net 从行号和行位置获取String中的位置

rt4zxlrg  于 2023-05-19  发布在  .NET
关注(0)|答案(2)|浏览(189)

我使用XmlReader解析通过套接字接收的XML数据。数据有时会被分解成单独的数据包,当这种情况发生时,XmlReader将为不完整的XML抛出XmlException。发生这种情况时,我希望保留部分XML消息,并将其与接收到的下一个数据连接起来,该数据将包含剩余的XML。我遇到的问题是只保留不完整的XML。
下面的示例XML(来自Sample XML File)说明了这个问题:

<book id="bk101">
  <author>Gambardella, Matthew</author>
  <title>XML Developer's Guide</title>
  <description>An in-depth look at creating applications 
  with XML.</description>
</book>
<book id="bk102">
  <author>Ralls, Kim</author>
  <title>Midnight Rain</title>
  <description>A former architect battles corporate zombies, 
  an evil sorceress, and her own childhood to become queen 
  of the world.</description>
</book>
<book id="bk103">
  <author>Corets, Eva</author>
  <title>Maeve Ascendant</title>
  <description>After the collapse of a nanotechnology 
  society in England, the young survivors lay the 
  foundation for a new society.</description>
</book>

假设一次交易中售出100本书,XML被分成两个包。第一个数据包可以这样结束:

<book id="bk103">
  <author>Corets, Eva</author>
  <title>Maeve Ascendant</title>
  <description>After the collapse of a nano

下面的包将包含XML的其余部分:

technology 
  society in England, the young survivors lay the 
  foundation for a new society.</description>
</book>

XmlReader将正确解析前两本书,我可以使用ReadOuterXml获取XML。然后它会在第三本书中抛出一个异常,所以我想从原始XML中只保留从<book id="bk103">开始的子字符串。XmlException给我错误的LineNumber和LinePosition,但这不是我想要的位置。相反,在读取每个XML元素XmlReader之后,我可以将XmlReader转换为IXmlLineInfo,并在调用ReadOuterXml之后获取读取器的位置。这将再次为我提供LineNumber和LinePosition。
我的问题是:如何将LineNumber和LinePosition转换为原始XML字符串中的索引。在我使用的XML示例中,XmlException将位于第17行的位置44。最后一个有效元素之后的位置将是第13行,位置8。我要找的职位是440。

TL;DR

我怎么从13号线8号位得到440。我希望使用原始XML的子字符串。

lb3vh1jj

lb3vh1jj1#

我使用下面的代码阅读巨大的xml文件。我添加了以前从未使用过的异常处理程序(需要为异常添加代码)。看看这个有没有用

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

namespace ConsoleApplication2
{
    class Program
    {
        const string URL = "URL";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(URL);

            while(!reader.EOF)
            {
                try
                {
                    if(reader.Name != "book")
                    {
                        reader.ReadToFollowing("book");
                    }
                }
                catch(Exception ex)
                {

                }
                try
                {
                    if(!reader.EOF)
                    {
                        XElement book = (XElement)XElement.ReadFrom(reader);
                    }
                }
                catch(Exception ex)
                {

                }
            }
        }
    }
 
}
twh00eeo

twh00eeo2#

一种简单的方法是循环查找System.Environment.NewLine的第12个示例的位置,然后将LinePosition的值添加到该位置:

string previousFragment = "";

while (!_cancellationToken.IsCancellationRequested)
{

    // Read from buffer
    string bufferData = _buffer.Take();
    string localBuffer = previousFragment + bufferData;

    // Clear out previous fragment
    previousFragment = "";

    using (TextReader textReader = new StringReader(localBuffer))
    {
        XmlReader xmlReader;
        xmlReader = XmlReader.Create(textReader, _xmlReaderSettings);

        int lastLine;
        int lastPosition;

        try
        {
            while (xmlReader.Read())
            {
                if (xmlReader.NodeType == XmlNodeType.Element)
                {
                    string validXml = xmlReader.ReadOuterXml;
                }

                IXmlLineInfo lineInfo = xmlReader;
                lastLine = lineInfo.LineNumber;
                lastPosition = lineInfo.LinePosition;
            }
        }
        catch (XmlException ex)
        {
            localBuffer = localBuffer.ReplaceLineEndings();
            int position = 0;

            for (int counter = 1; counter <= lastLine - 1; counter++)
                position = localBuffer.IndexOf(System.Environment.NewLine, position + 1);
            position += lastPosition + 1;

            previousFragment = localBuffer.Substring(position);
        }
    }
}

在这段代码中:

  1. _buffer是从socket接收的String数据的BlockingCollection
  2. _xmlReaderSettings是一个XmlReaderSettings对象,ValidationType设置为ValidationType.None,ConformanceLevel设置为ConformanceLevel.Fragment
    1.此代码作为任务运行。当新的XML到达时,它被添加到_buffer
    有没有更好的办法?

相关问题