如何分割一个大的XML文件?

我们将“logging”导出到一个xml文件; 我们的一位客户抱怨说,这个文件对于其他系统来说太大了。 因此,我需要分割文件,同时在每个新文件中重复“标题部分”。

所以我正在寻找的东西,可以让我为应该总是输出的部分定义一些xpaths和另一个xpath的“行”与一个参数,说明有多less行放在每个文件,以及如何命名文件。

在开始编写一些自定义的.net代码之前, 有没有一个标准的命令行工具,将在Windows上工作呢

(因为我知道如何在C#中编程,我更多地被写入代码,然后尝试复杂的xsl等,但“自我”的解决scheme会更好,然后自定义代码。)

Solutions Collecting From Web of "如何分割一个大的XML文件?"

“有没有一个标准的命令行工具,可以在Windows上工作?”

是。 http://xponentsoftware.com/xmlSplit.aspx

没有通用的解决方案,因为有很多不同的方式可以构建源XML。

构建一个将输出一个XML文档片段的XSLT转换是相当直接的。 例如,给定这个XML:

<header> <data rec="1"/> <data rec="2"/> <data rec="3"/> <data rec="4"/> <data rec="5"/> <data rec="6"/> </header> 

您可以使用此XSLT输出仅包含特定范围内的data元素的文件的副本:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:param name="startPosition"/> <xsl:param name="endPosition"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="header"> <xsl:copy> <xsl:apply-templates select="data"/> </xsl:copy> </xsl:template> <xsl:template match="data"> <xsl:if test="position() &gt;= $startPosition and position() &lt;= $endPosition"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:if> </xsl:template> </xsl:stylesheet> 

(顺便说一下,因为这是基于身份转换的,所以即使header不是顶层元素,也可以工作。)

您仍然需要对源XML中的data元素进行计数,并使用适合该情况的$startPosition$endPosition的值重复运行变换。

首先从这个链接http://www.firstobject.com/foxe242.zip下载foxe xml编辑器

观看视频http://www.firstobject.com/xml-splitter-script-video.htm视频介绍了分割代码是如何工作的&#x3002;

该页面上有一个脚本代码(以split()开始)复制代码,并在xml编辑器程序中创建“File”下的“New Program”。 粘贴代码并保存。 代码是:

 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; } 

根据需要更改粗体标记(或** **标记)的字段。 (这也表示在视频页面)

在xml编辑器窗口中,右键单击并单击RUN(或简单地F9)。 在窗口上有输出栏,它显示了生成的文件的数量。

注意:输入文件名可以是"C:\\Users\\AUser\\Desktop\\a_xml_file.xml" (双斜线),输出文件为"C:\\Users\\AUser\\Desktop\\anoutputfolder\\piece" + nFileCount + ".xml"

没有什么能够轻松应对这种情况的。

你的方法听起来很合理,不过我可能从一个包含需要重复的元素的“骨架”文档开始,并用“记录”生成几个文档。


更新:

经过一番挖掘,我发现这篇文章描述了使用XSLT分割文件的方法。

xml_split – 将巨大的XML文档分割成更小的块

http://www.perlmonks.org/index.pl?node_id=429707

http://metacpan.org/pod/XML::Twig

正如前面提到的,来自Perl 包 XML :: Twig的xml_split做得非常好。

用法

 xml_split < bigFile.xml #or if compressed eg bzcat bigFile.xml.bz2 | xml_split 

没有任何参数xml_split为每个顶级子节点创建一个文件。

有参数可以指定每个文件( -g )或近似大小( -s <Kb|Mb|Gb> )所需的元素数量。

安装

视窗

看这里

Linux的

sudo apt-get install xml-twig-tools

使用基于https://www.ultraedit.com/forums/viewtopic.php?f=52&t=6704&#x7684; Ultraedit

所有我添加了一些XML页眉和页脚位第一个和最后一个文件需要手动修复(或从您的源删除根元素)。

  // from https://www.ultraedit.com/forums/viewtopic.php?f=52&t=6704 var FoundsPerFile = 200; // Global setting for number of found split strings per file. var SplitString = "</letter>"; // String where to split. The split occurs after next character. var xmlHead = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'; var xmlRootStart = '<letters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" letterCode="OA01" >'; var xmlRootEnd = '</letters>'; /* Find the tab index of the active document */ // Copied from http://www.ultraedit.com/forums/viewtopic.php?t=4571 function getActiveDocumentIndex () { var tabindex = -1; /* start value */ for (var i = 0; i < UltraEdit.document.length; i++) { if (UltraEdit.activeDocument.path==UltraEdit.document[i].path) { tabindex = i; break; } } return tabindex; } if (UltraEdit.document.length) { // Is any file open? // Set working environment required for this job. UltraEdit.insertMode(); UltraEdit.columnModeOff(); UltraEdit.activeDocument.hexOff(); UltraEdit.ueReOn(); // Move cursor to top of active file and run the initial search. UltraEdit.activeDocument.top(); UltraEdit.activeDocument.findReplace.searchDown=true; UltraEdit.activeDocument.findReplace.matchCase=true; UltraEdit.activeDocument.findReplace.matchWord=false; UltraEdit.activeDocument.findReplace.regExp=false; // If the string to split is not found in this file, do nothing. if (UltraEdit.activeDocument.findReplace.find(SplitString)) { // This file is probably the correct file for this script. var FileNumber = 1; // Counts the number of saved files. var StringsFound = 1; // Counts the number of found split strings. var NewFileIndex = UltraEdit.document.length; /* Get the path of the current file to save the new files in the same directory as the current file. */ var SavePath = ""; var LastBackSlash = UltraEdit.activeDocument.path.lastIndexOf("\\"); if (LastBackSlash >= 0) { LastBackSlash++; SavePath = UltraEdit.activeDocument.path.substring(0,LastBackSlash); } /* Get active file index in case of more than 1 file is open and the current file does not get back the focus after closing the new files. */ var FileToSplit = getActiveDocumentIndex(); // Always use clipboard 9 for this script and not the Windows clipboard. UltraEdit.selectClipboard(9); // Split the file after every x found split strings until source file is empty. while (1) { while (StringsFound < FoundsPerFile) { if (UltraEdit.document[FileToSplit].findReplace.find(SplitString)) StringsFound++; else { UltraEdit.document[FileToSplit].bottom(); break; } } // End the selection of the find command. UltraEdit.document[FileToSplit].endSelect(); // Move the cursor right to include the next character and unselect the found string. UltraEdit.document[FileToSplit].key("RIGHT ARROW"); // Select from this cursor position everything to top of the file. UltraEdit.document[FileToSplit].selectToTop(); // Is the file not already empty? if (UltraEdit.document[FileToSplit].isSel()) { // Cut the selection and paste it into a new file. UltraEdit.document[FileToSplit].cut(); UltraEdit.newFile(); UltraEdit.document[NewFileIndex].setActive(); UltraEdit.activeDocument.paste(); /* Add line termination on the last line and remove automatically added indent spaces/tabs if auto-indent is enabled if the last line is not already terminated. */ if (UltraEdit.activeDocument.isColNumGt(1)) { UltraEdit.activeDocument.insertLine(); if (UltraEdit.activeDocument.isColNumGt(1)) { UltraEdit.activeDocument.deleteToStartOfLine(); } } // add headers and footers UltraEdit.activeDocument.top(); UltraEdit.activeDocument.write(xmlHead); UltraEdit.activeDocument.write(xmlRootStart); UltraEdit.activeDocument.bottom(); UltraEdit.activeDocument.write(xmlRootEnd); // Build the file name for this new file. var SaveFileName = SavePath + "LETTER"; if (FileNumber < 10) SaveFileName += "0"; SaveFileName += String(FileNumber) + ".raw.xml"; // Save the new file and close it. UltraEdit.saveAs(SaveFileName); UltraEdit.closeFile(SaveFileName,2); FileNumber++; StringsFound = 0; /* Delete the line termination in the source file if last found split string was at end of a line. */ UltraEdit.document[FileToSplit].endSelect(); UltraEdit.document[FileToSplit].key("END"); if (UltraEdit.document[FileToSplit].isColNumGt(1)) { UltraEdit.document[FileToSplit].top(); } else { UltraEdit.document[FileToSplit].deleteLine(); } } else break; UltraEdit.outputWindow.write("Progress " + SaveFileName); } // Loop executed until source file is empty! // Close source file without saving and re-open it. var NameOfFileToSplit = UltraEdit.document[FileToSplit].path; UltraEdit.closeFile(NameOfFileToSplit,2); /* The following code line could be commented if the source file is not needed anymore for further actions. */ UltraEdit.open(NameOfFileToSplit); // Free memory and switch back to Windows clipboard. UltraEdit.clearClipboard(); UltraEdit.selectClipboard(0); } }