C# 按字节大小对XML文件进行预测性拆分

C# 按字节大小对XML文件进行预测性拆分,c#,xml,linq,linq-to-xml,C#,Xml,Linq,Linq To Xml,我有XML消息xmlStr,必须将其拆分为更小的XML消息,这些消息小于或等于maxSizeBytes。这是通过将文档的根和它的第一个子元素作为较小XML的基础,并获取一些元素,并将它们的数量放入新形成的(较小的)XML消息中来实现的 <?xml version="1.0"?> <Bas> <Hdr> <Smt>...</Smt> <Smt>...</Smt> <Smt>.

我有XML消息
xmlStr
,必须将其拆分为更小的XML消息,这些消息小于或等于
maxSizeBytes
。这是通过将文档的根和它的第一个子元素作为较小XML的基础,并获取一些
元素,并将它们的数量放入新形成的(较小的)XML消息中来实现的

<?xml version="1.0"?>
<Bas>
  <Hdr>
    <Smt>...</Smt>
    <Smt>...</Smt>
    <Smt>...</Smt>
   </Hdr>
</Bas>
我很快发现,较小XML文件的字节大小大于
maxSizeBytes
,因为XDocument会在每条消息中添加额外字符,从而增加字节大小

基本算法是:

  • 获取包含空
    Hdr
    元素的文档的大小。请注意,默认编码是UTF-8。所以我使用
    Encoding.Default.GetByteCount
    来计算文档的大小及其元素
  • 为每个子文档克隆此空hdr文档
  • 对于eash
    Smt
    元素,请在添加前检查子文档大小是否超过最大值
带注释的代码

var doc = XDocument.Load("data.xml");
var hdr = xdoc.Root.Element("Hdr");
var elements = hdr.Elements().ToList(); 
hdr.RemoveAll(); // we can remove child elements, because they are stored in a list
hdr.Value = "";  // otherwise xdoc will compact empty element to <Hdr/>

// calculating size of sub-document 'template'
var sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb))
    doc.Save(writer);
var outerSizeInBytes = Encoding.Default.GetByteCount(sb.ToString());

var maxSizeInBytes = 100;
var subDocumentIndex = 0; // used just for naming sub-document files
var subDocumentSizeBytes = outerSizeInBytes; // initial size of any sub-document
var subDocument = new XDocument(doc); // clone 'template'

foreach (var smt in elements)
{
    var currentElementSizeBytes = Encoding.Default.GetByteCount(smt.ToString());

    if (maxSizeInBytes < subDocumentSizeBytes + currentElementSizeBytes
        && subDocumentSizeBytes != outerSizeInBytes) // case when first element is too big
    {
        subDocument.Save($"doc{++subDocumentIndex}.xml");
        subDocument = new XDocument(doc);
        subDocumentSizeBytes = outerSizeInBytes;
    }

    subDocument.Root.Element("Hdr").Add(smt);
    subDocumentSizeBytes += currentElementSizeBytes;
}

// if current sub-document has elements added, save it too
if (outerSizeInBytes < subDocumentSizeBytes)
    subDocument.Save($"doc{++subDocumentIndex}.xml");
var doc=XDocument.Load(“data.xml”);
var hdr=xdoc.Root.Element(“hdr”);
var elements=hdr.elements().ToList();
hdr.RemoveAll();//我们可以删除子元素,因为它们存储在列表中
hdr.Value=“”;//否则xdoc将压缩空元素到
//正在计算子文档“模板”的大小
var sb=新的StringBuilder();
使用(XmlWriter=XmlWriter.Create(sb))
保存文档(编写器);
var outerSizeInBytes=Encoding.Default.GetByteCount(sb.ToString());
var maxSizeInBytes=100;
var subDocumentIndex=0;//仅用于命名子文档文件
var subDocumentSizeBytes=outerSizeInBytes;//任何子文档的初始大小
var子文档=新XDocument(doc);//克隆“模板”
foreach(元件中的var smt)
{
var currentElementSizeBytes=Encoding.Default.GetByteCount(smt.ToString());
如果(maxSizeInBytes

当source为且最大大小为250字节时,您将获得三个文档

<?xml version="1.0"?>
<Bas>
  <Hdr>
    <Smt>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</Smt>
    <Smt>Contrary to popular belief, Lorem Ipsum is not simply random text.</Smt>
    <Smt>It has survived not only five centuries, 
 but also the leap into electronic typesetting, remaining essentially unchanged.</Smt>
    <Smt>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Smt>
  </Hdr>
</Bas>

Lorem Ipsum只是印刷和排版行业的虚拟文本。
与流行的观点相反,Lorem Ipsum不是简单的随机文本。
它不仅存活了五个世纪,
但也向电子排版迈进,基本保持不变。
Lorem ipsum dolor sit amet,是一位杰出的献身者。
doc1(223字节):


Lorem Ipsum只是印刷和排版行业的虚拟文本。
与流行的观点相反,Lorem Ipsum不是简单的随机文本。
doc2(259字节,单个元素):


它不仅存活了五个世纪,
但也向电子排版迈进,基本保持不变。
doc3(128字节,最后一个)


Lorem ipsum dolor sit amet,是一位杰出的献身者。
基本算法是:

  • 获取包含空
    Hdr
    元素的文档的大小。请注意,默认编码是UTF-8。所以我使用
    Encoding.Default.GetByteCount
    来计算文档的大小及其元素
  • 为每个子文档克隆此空hdr文档
  • 对于eash
    Smt
    元素,请在添加前检查子文档大小是否超过最大值
带注释的代码

var doc = XDocument.Load("data.xml");
var hdr = xdoc.Root.Element("Hdr");
var elements = hdr.Elements().ToList(); 
hdr.RemoveAll(); // we can remove child elements, because they are stored in a list
hdr.Value = "";  // otherwise xdoc will compact empty element to <Hdr/>

// calculating size of sub-document 'template'
var sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb))
    doc.Save(writer);
var outerSizeInBytes = Encoding.Default.GetByteCount(sb.ToString());

var maxSizeInBytes = 100;
var subDocumentIndex = 0; // used just for naming sub-document files
var subDocumentSizeBytes = outerSizeInBytes; // initial size of any sub-document
var subDocument = new XDocument(doc); // clone 'template'

foreach (var smt in elements)
{
    var currentElementSizeBytes = Encoding.Default.GetByteCount(smt.ToString());

    if (maxSizeInBytes < subDocumentSizeBytes + currentElementSizeBytes
        && subDocumentSizeBytes != outerSizeInBytes) // case when first element is too big
    {
        subDocument.Save($"doc{++subDocumentIndex}.xml");
        subDocument = new XDocument(doc);
        subDocumentSizeBytes = outerSizeInBytes;
    }

    subDocument.Root.Element("Hdr").Add(smt);
    subDocumentSizeBytes += currentElementSizeBytes;
}

// if current sub-document has elements added, save it too
if (outerSizeInBytes < subDocumentSizeBytes)
    subDocument.Save($"doc{++subDocumentIndex}.xml");
var doc=XDocument.Load(“data.xml”);
var hdr=xdoc.Root.Element(“hdr”);
var elements=hdr.elements().ToList();
hdr.RemoveAll();//我们可以删除子元素,因为它们存储在列表中
hdr.Value=“”;//否则xdoc将压缩空元素到
//正在计算子文档“模板”的大小
var sb=新的StringBuilder();
使用(XmlWriter=XmlWriter.Create(sb))
保存文档(编写器);
var outerSizeInBytes=Encoding.Default.GetByteCount(sb.ToString());
var maxSizeInBytes=100;
var subDocumentIndex=0;//仅用于命名子文档文件
var subDocumentSizeBytes=outerSizeInBytes;//任何子文档的初始大小
var子文档=新XDocument(doc);//克隆“模板”
foreach(元件中的var smt)
{
var currentElementSizeBytes=Encoding.Default.GetByteCount(smt.ToString());
如果(maxSizeInBytes

当source为且最大大小为250字节时,您将获得三个文档

<?xml version="1.0"?>
<Bas>
  <Hdr>
    <Smt>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</Smt>
    <Smt>Contrary to popular belief, Lorem Ipsum is not simply random text.</Smt>
    <Smt>It has survived not only five centuries, 
 but also the leap into electronic typesetting, remaining essentially unchanged.</Smt>
    <Smt>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Smt>
  </Hdr>
</Bas>

Lorem Ipsum只是印刷和排版行业的虚拟文本。
与流行的观点相反,Lorem Ipsum不是简单的随机文本。
它不仅存活了五个世纪,
但也向电子排版迈进,基本保持不变。
Lorem ipsum dolor sit amet,是一位杰出的献身者。
doc1(223字节):


Lorem Ipsum只是印刷和排版行业的虚拟文本。
与流行的观点相反,Lorem Ipsum不是简单的随机文本。
doc2(259字节,单个元素):


它不仅存活了五个世纪
<?xml version="1.0" encoding="utf-8"?>
<Bas>
  <Hdr>
    <Smt>It has survived not only five centuries, 
 but also the leap into electronic typesetting, remaining essentially unchanged.</Smt>
  </Hdr>
</Bas>
<?xml version="1.0" encoding="utf-8"?>
<Bas>
  <Hdr>
    <Smt>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Smt>
  </Hdr>
</Bas>