2017-04-10 4 views
0

xmlStrという小さなXMLメッセージに分割する必要があるXMLメッセージmaxSizeBytesがあります。これは、ドキュメントのルートをとって、最初の子をより小さなXMLのベースとし、いくつかの数の<Smt>要素をとり、新しく形成された(小さい)XMLメッセージにそれらの数を入れることによって行われます。XMLファイルをバイトサイズで予測分割する

<?xml version="1.0"?> 
<Bas> 
    <Hdr> 
    <Smt>...</Smt> 
    <Smt>...</Smt> 
    <Smt>...</Smt> 
    </Hdr> 
</Bas> 

現在、私は小さなXMLに入れるsmtNodesPerMessageノードを取る に続くメッセージ全体のサイズint smtNodesPerMessage = (int)Math.Ceiling((double)ASCIIEncoding.ASCII.GetByteCount(xmlStr)/(double)maxSizeBytes);、測定しています:

//doc is original XDocument message 
XDocument splitXML = new XDocument(new XElement(doc.Root.Name,            
            doc.Root.Descendants("Hdr"))); 
splitXML.Root.Add(batchOfSmt); 

を私はすぐに、見つけた小さなXMLファイルのバイトサイズが大きいことですmaxSizeBytesより大きい。なぜなら、XDocumentは各メッセージに余分な文字を追加し、バイトサイズを増やすからである。

+0

興味深いです。どうすればいいのか教えてください – MickyD

+0

コードはおそらく各メッセージにxml IDを追加しています:<?xml version = "1.0"?> – jdweng

+0

@jdweng、私は 'splitXML.Declaration = doc.Declaration;上のコード。 – newprint

答えて

2

基本的なアルゴリズムは次のとおりです。

  • は空Hdr要素を持つ文書のサイズを取得します。デフォルトのエンコーディングはUTF-8です。だから私はEncoding.Default.GetByteCountを文書の大きさをcalcualteに使用しました。
  • コメント

    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"); 
    

サブ文書サイズが最大値を超えるかどうかをチェックするコードを追加する前にクローン各サブ文書eash Smt要素について
  • ため、この空HDR文書を

    ソースがあり、最大サイズが250バイトの場合、3つの文書が得られます

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

    DOC1(223バイト):

    <?xml version="1.0" encoding="utf-8"?> 
    <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> 
        </Hdr> 
    </Bas> 
    

    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> 
    

    DOC3(128のバイト、最後のもの)

    <?xml version="1.0" encoding="utf-8"?> 
    <Bas> 
        <Hdr> 
        <Smt>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Smt> 
        </Hdr> 
    </Bas> 
    
  • +1

    ascii.GetBytesCountを使用する場合は、xmlエンコーディングをasciiとして宣言する方が良い(xml宣言で)。 – Evk

    +0

    @Evk同意すると、私はちょうど質問からバイト計算方法をコピーしました。実際には、Unicodeがそこに使われるべきだと思っています。 –

    +0

    はい、私はUTF-8を使うべきだと思います。 – Evk

    関連する問題