كيف يمكنني تقسيم مستند XML الى الثلثين (أو حتى أفضل ، ن القطع)?

StackOverflow https://stackoverflow.com/questions/7846

  •  08-06-2019
  •  | 
  •  

سؤال

وأود أن استخدام اللغة التي أنا على دراية - Java, C#, روبي, PHP, C/C++, على الرغم من أن الأمثلة في أي لغة أو شبة الكود أكثر من موضع ترحيب.

ما هي أفضل طريقة تقسيم كبير XML المستند إلى مقاطع أصغر لا تزال صالحة XML ؟ لأغراض بلدي, أنا بحاجة إلى تقسيمها إلى ما يقرب من ثلثي أو أرباع, ولكن من أجل تقديم أمثلة انقسموا إلى n مكونات من شأنها أن تكون جيدة.

هل كانت مفيدة؟

المحلول

بالطبع يمكنك دائما استخراج عناصر المستوى الأعلى (إذا كان هذا هو تحبب تريد متروك لكم).في C# ، XmlDocument الدرجة.على سبيل المثال, إذا كان لديك ملف XML بدا شيء من هذا القبيل:

<Document>
  <Piece>
     Some text
  </Piece>
  <Piece>
     Some other text
  </Piece>
</Document>

إذا كنت تستخدم التعليمات البرمجية مثل هذا إلى استخراج جميع القطع:

XmlDocument doc = new XmlDocument();
doc.Load("<path to xml file>");
XmlNodeList nl = doc.GetElementsByTagName("Piece");
foreach (XmlNode n in nl)
{
    // Do something with each Piece node
}

مرة كنت قد حصلت على العقد ، يمكنك أن تفعل شيئا معهم في التعليمات البرمجية الخاصة بك, أو يمكنك نقل النص بأكمله من عقدة إلى مستند XML والعمل على ذلك كما لو كانت قطعة مستقلة من XML (بما في ذلك حفظه إلى القرص ، إلخ).

نصائح أخرى

تحليل مستندات XML باستخدام DOM لا مقياس.

هذا رائع-السيناريو هو استخدام ستاكس (الجري API for XML) إلى تقسيم مستند XML بين عناصر المستوى الأعلى (الذي أسهم نفس QName كما الطفل الأول من الجذر-الوثيقة).انها سريعة جدا, مقابض التعسفي عدد كبير من الوثائق و هي مفيدة جدا عندما تريد تقسيم دفعة كبيرة الملف إلى أجزاء أصغر.

يتطلب رائع على جافا 6 أو ستاكس API تنفيذ مثل Woodstox في CLASSPATH

import javax.xml.stream.*

pieces = 5
input = "input.xml"
output = "output_%04d.xml"
eventFactory = XMLEventFactory.newInstance()
fileNumber = elementCount = 0

def createEventReader() {
    reader = XMLInputFactory.newInstance().createXMLEventReader(new FileInputStream(input))
    start = reader.next()
    root = reader.nextTag()
    firstChild = reader.nextTag()
    return reader
}

def createNextEventWriter () {
    println "Writing to '${filename = String.format(output, ++fileNumber)}'"
    writer = XMLOutputFactory.newInstance().createXMLEventWriter(new FileOutputStream(filename), start.characterEncodingScheme)
    writer.add(start)
    writer.add(root)
    return writer
}

elements = createEventReader().findAll { it.startElement && it.name == firstChild.name }.size()
println "Splitting ${elements} <${firstChild.name.localPart}> elements into ${pieces} pieces"
chunkSize = elements / pieces
writer = createNextEventWriter()
writer.add(firstChild)
createEventReader().each { 
    if (it.startElement && it.name == firstChild.name) {
        if (++elementCount > chunkSize) {
            writer.add(eventFactory.createEndDocument())
            writer.flush()
            writer = createNextEventWriter()
            elementCount = 0
        }
    }
    writer.add(it)
}
writer.flush()

كما DannySmurf اللمسات هنا هو كل شيء عن بنية مستند xml.
إذا كنت اثنين فقط ضخمة "أعلى مستوى" العلامات ، فإنه سوف يكون من الصعب للغاية أن تكون قادرة على الانقسام بطريقة يجعل من الممكن دمج كل ذلك معا مرة أخرى و قراءة قطعة قطعة صالحة xml.

نظرا وثيقة مع الكثير من قطع منفصلة مثل تلك التي في DannySmurfs سبيل المثال ، ينبغي أن يكون من السهل إلى حد ما.
بعض الخام البرمجية الزائفة في C# :

int nrOfPieces = 5;
XmlDocument xmlOriginal = some input parameter..

// construct the list we need, and fill it with XmlDocuments..
var xmlList = new List<XmlDocument>();
for (int i = 0; i < nrOfPieces ; i++)
{
    var xmlDoc = new XmlDocument();
    xmlDoc.ChildNodes.Add(new XmlNode(xmlOriginal.FistNode.Name));
    xmlList.Add(xmlDoc);
}

var nodeList = xmlOriginal.GetElementsByTagName("Piece")M
// Copy the nodes from the original into the pieces..
for (int i = 0; i < nodeList .Count; i++)
{
    var xmlDoc = xmlList[i % nrOfPieces];
    var nodeToCopy = nodeList[i].Clone();
    xmlDoc.FirstNode.ChildNodes.Add(nodeToCopy);
}

هذا يجب أن تعطيك ن المستندات مع الصحيح xml وإمكانية دمجها معا مرة أخرى.
ولكن مرة أخرى, هذا يعتمد على ملف xml.

هذا هو أكثر من تعليق من إجابة, ولكن لن:

XmlDocument doc = new XmlDocument();
doc.Load("path");

قراءة الملف بأكمله في وقت واحد ؟ اعتقد انه يجب رفع نقطة منذ من نظرة توماس السؤال فهو قلق قراءة الملفات الكبيرة و يريد تقسيم العملية..

ذلك أن قراءة الملف بأكمله في وقت واحد.في تجربتي, رغم أن, إذا كنت مجرد قراءة ملف به بعض المعالجة (أي كسر الأمر) ومن ثم الاستمرار في العمل الخاص بك ، XmlDocument هو ذاهب للذهاب من خلال ذلك إنشاء/قراءة/جمع دورة بسرعة بحيث أنه من المحتمل أن لا يهم.

بالطبع هذا يعتمد على ما "كبيرة" الملف.إذا كان 30 ميجا بايت ملف XML (التي أود أن تنظر كبيرة في ملف XML) ، فإنه على الأرجح لن يحدث أي فارق.لو كان 500 ميجا بايت ملف XML باستخدام XmlDocument سوف تصبح إشكالية للغاية على أنظمة دون كمية كبيرة من ذاكرة الوصول العشوائي (في هذه الحالة ، ومع ذلك ، أود القول أن الوقت يدويا من خلال اختيار الملف XmlReader سيكون أكبر عائق كبير).

لست متأكدا أي نوع من المعالجة تفعله ولكن كبيرة جدا XML, لقد كنت دائما من المعجبين من الحدث القائم على المعالجة.ربما هو بلدي جافا الخلفية, ولكن أنا حقا مثل ساكس.تحتاج إلى إدارة الدولة ، ولكن مرة واحدة يمكنك الحصول على الماضي, انها فعالة جدا طريقة تحليل XML.

http://saxdotnet.sourceforge.net/

انا ذاهب للذهاب مع youphoric على هذا واحد.لملفات كبيرة جدا ساكس (أو أي محلل تدفق) أن يكون عونا كبيرا في المعالجة.باستخدام DOM يمكنك جمع فقط أعلى مستوى العقد, ولكن لا يزال لديك تحليل الوثيقة بأكملها القيام بذلك باستخدام محلل تدفق والحدث القائم على معالجة يتيح لك "تخطي" العقد كنت لا ترغب في ؛ يجعل المعالجة بشكل أسرع.

إذا لم تكن تماما حساسية بيرل ، ثم XML::غصين يأتي مع أداة اسمه xml_split يمكن تقسيم مستند إنتاج XML القسم.يمكنك تقسيم على مستوى من الشجرة ، حسب الحجم أو على تعبير XPath.

يبدو أنك تعمل مع C#.NET framework 3.5.لقد جئت عبر بعض الوظائف التي تشير إلى استخدام العائد نوع الخوارزمية على ملف تيار مع XmlReader.

هنا بضعة بلوق وظيفة للحصول على انك بدأت في الطريق:

لم يوتيوب فيديو يظهر كيفية تقسيم ملفات XML مع foxe (الحرة محرر XML من Firstobject) فقط باستخدام كمية صغيرة من الذاكرة بغض النظر عن حجم المدخلات والمخرجات الملفات.

استخدام الذاكرة في هذا CMarkup XML القارئ (سحب محلل) و XML الكاتب الحل يعتمد على حجم الثانوية التي فردي نقلها من ملف الإدخال إلى ملفات الإخراج ، أو الحد الأدنى من حجم كتلة من 16 كيلو بايت.

split()
{
  CMarkup xmlInput, xmlOutput;
  xmlInput.Open( "50MB.xml", MDF_READFILE );
  int nObjectCount = 0, nFileCount = 0;
  while ( xmlInput.FindElem("//ACT") )
  {
    if ( nObjectCount == 0 )
    {
      ++nFileCount;
      xmlOutput.Open( "piece" + nFileCount + ".xml", MDF_WRITEFILE );
      xmlOutput.AddElem( "root" );
      xmlOutput.IntoElem();
    }
    xmlOutput.AddSubDoc( xmlInput.GetSubDoc() );
    ++nObjectCount;
    if ( nObjectCount == 5 )
    {
      xmlOutput.Close();
      nObjectCount = 0;
    }
  }
  if ( nObjectCount )
    xmlOutput.Close();
  xmlInput.Close();
  return nFileCount;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top