2008-08-11 32 views
7

Tôi muốn sử dụng một ngôn ngữ mà tôi quen thuộc với - Java, C#, Ruby, PHP, C/C++, mặc dù các ví dụ trong bất kỳ ngôn ngữ hoặc mã giả nào được hoan nghênh hơn.Làm cách nào để tách một tài liệu XML thành ba phần (hoặc thậm chí tốt hơn, n phần)?

Cách tốt nhất để tách một tài liệu XML lớn thành các phần nhỏ hơn vẫn là XML hợp lệ là gì? Vì mục đích của tôi, tôi cần chia chúng thành khoảng ba phần ba hoặc bốn phần tư, nhưng vì mục đích cung cấp các ví dụ, tách chúng thành các thành phần n sẽ là tốt.

Trả lời

3

Tất nhiên, bạn luôn có thể trích xuất các phần tử cấp cao nhất (cho dù đây là mức độ chi tiết bạn muốn tùy thuộc vào bạn). Trong C#, bạn sẽ sử dụng lớp XmlDocument. Ví dụ, nếu tập tin XML của bạn trông như thế này:

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

sau đó bạn muốn sử dụng mã như thế này để trích xuất tất cả các miếng:

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 
} 

Một khi bạn đã có các nút, bạn có thể làm điều gì đó với chúng trong mã của bạn, hoặc bạn có thể chuyển toàn bộ văn bản của nút sang tài liệu XML của chính nó và hành động như thể nó là một đoạn XML độc lập (bao gồm lưu nó trở lại đĩa, v.v.).

1

Đây là chi tiết của một bình luận hơn là một câu trả lời, nhưng sẽ không:

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

Đọc toàn bộ tập tin cùng một lúc? Chỉ cần nghĩ rằng tôi nên tăng điểm kể từ khi nhìn vào câu hỏi của Thomas, ông quan tâm đến việc đọc các tập tin lớn và muốn phá vỡ quá trình ..

3

Như DannySmurf chạm vào đây, tất cả là về cấu trúc của tài liệu xml.
Nếu bạn chỉ có hai thẻ "cấp cao nhất", nó sẽ cực kỳ khó để có thể phân chia nó theo cách làm cho cả hai có thể hợp nhất lại với nhau và đọc từng mảnh như xml hợp lệ.

Đưa ra một tài liệu có nhiều phần riêng biệt như các ví dụ trong ví dụ DannySmurfs, nó sẽ khá dễ dàng.
Một số mã thô trong Pseudo 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); 
} 

này sẽ cho bạn n docs với xml chính xác và khả năng kết hợp chúng lại với nhau.
Nhưng một lần nữa, nó phụ thuộc vào tệp xml.

1

Nó sẽ đọc toàn bộ tệp cùng một lúc. Tuy nhiên, theo kinh nghiệm của tôi, nếu bạn chỉ đọc tệp, thực hiện một số xử lý (ví dụ, phá vỡ nó) và sau đó tiếp tục với công việc của bạn, XmlDocument sẽ trải qua quá trình tạo/đọc/thu thập dữ liệu nhanh đến mức nó có thể sẽ không thành vấn đề.

Tất nhiên, điều đó phụ thuộc vào tệp "lớn". Nếu đó là một tập tin XML 30 MB (mà tôi sẽ xem xét lớn cho một tập tin XML), nó có thể sẽ không tạo ra bất kỳ sự khác biệt nào. Nếu đó là tệp XML 500 MB, việc sử dụng XmlDocument sẽ trở nên cực kỳ có vấn đề trên các hệ thống không có RAM đáng kể (trong trường hợp đó, tuy nhiên, tôi cho rằng thời gian để chọn thủ công thông qua tệp bằng XmlReader sẽ quan trọng hơn trở ngại).

0

Dường như bạn đang làm việc với C# và .NET 3.5. Tôi đã đi qua một số bài viết đề nghị sử dụng một loại lợi nhuận của thuật toán trên một dòng tập tin với một XmlReader.

Dưới đây là một bài viết vài blog để giúp bạn bắt đầu xuống đường dẫn:

0

Không chắc chắn về loại chế biến bạn đang làm, nhưng đối với XML rất lớn , Tôi luôn là người hâm mộ xử lý dựa trên sự kiện. Có lẽ đó là nền Java của tôi, nhưng tôi thực sự thích SAX. Bạn cần phải làm quản lý nhà nước của riêng bạn, nhưng một khi bạn vượt qua điều đó, đó là một phương pháp phân tích cú pháp XML rất hiệu quả.

http://saxdotnet.sourceforge.net/

0

Tôi sẽ đi cùng với lời nói độc trên trang này. Đối với các tệp rất lớn SAX (hoặc bất kỳ trình phân tích cú pháp trực tuyến nào khác) sẽ là một trợ giúp tuyệt vời trong quá trình xử lý. Sử dụng DOM, bạn có thể thu thập các nút cấp cao nhất, nhưng bạn vẫn phải phân tích toàn bộ tài liệu để thực hiện ... bằng cách sử dụng trình phân tích cú pháp trực tuyến và xử lý dựa trên sự kiện cho phép bạn "bỏ qua" các nút mà bạn không quan tâm; làm cho quá trình xử lý nhanh hơn.

0

Nếu bạn không hoàn toàn bị dị ứng với Perl, thì XML::Twig đi kèm với công cụ có tên xml_split có thể chia tách tài liệu, tạo ra phần XML được định dạng tốt. Bạn có thể phân chia theo cấp độ của cây, theo kích thước hoặc trên biểu thức XPath.

5

Phân tích cú pháp tài liệu XML bằng DOM không quy mô lớn.

Điều này Groovy -script đang sử dụng StAX (API trực tuyến cho XML) để chia tài liệu XML giữa các phần tử cấp cao nhất (chia sẻ cùng một QName làm con đầu tiên của tài liệu gốc). Nó khá nhanh, xử lý các tài liệu lớn tùy ý và rất hữu ích khi bạn muốn chia một tập tin batch lớn thành các phần nhỏ hơn.

Yêu cầu Groovy trên Java 6 hoặc một API Stax và thực hiện như Woodstox trong 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() 
0

Tôi đã làm một video trên YouTube cho thấy how to split XML files với foxe (trình biên tập XML miễn phí từ Firstobject) chỉ sử dụng một lượng nhỏ bộ nhớ bất kể kích thước của các tệp đầu vào và đầu ra.

Việc sử dụng bộ nhớ cho trình đọc XML CMarkup (trình phân tích cú pháp kéo) và giải pháp ghi XML phụ thuộc vào kích thước của các subdocuments được chuyển riêng từ tệp đầu vào sang tệp đầu ra hoặc kích thước khối tối thiểu 16 KB.

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; 
}
Các vấn đề liên quan