【发布时间】:2011-09-13 21:44:07
【问题描述】:
我看到了很多关于将 XML 文件拆分成更小的块的帖子/博客/文章,并决定创建自己的,因为我有一些自定义要求。这就是我的意思,请考虑以下 XML:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<company>
<staff id="1">
<firstname>yong</firstname>
<lastname>mook kim</lastname>
<nickname>mkyong</nickname>
<salary>100000</salary>
</staff>
<staff id="2">
<firstname>yong</firstname>
<lastname>mook kim</lastname>
<nickname>mkyong</nickname>
<salary>100000</salary>
</staff>
<staff id="3">
<firstname>yong</firstname>
<lastname>mook kim</lastname>
<nickname>mkyong</nickname>
<salary>100000</salary>
</staff>
<staff id="4">
<firstname>yong</firstname>
<lastname>mook kim</lastname>
<nickname>mkyong</nickname>
<salary>100000</salary>
</staff>
<staff id="5">
<firstname>yong</firstname>
<lastname>mook kim</lastname>
<salary>100000</salary>
</staff>
</company>
我想将此 xml 拆分为 n 个部分,每个部分包含 1 个文件,但 staff 元素必须包含 nickname ,如果它不存在我不想要它。所以这应该产生 4 个 xml 拆分,每个包含从 1 到 4 的员工 ID。
这是我的代码:
public int split() throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(inputFilePath)));
String line;
List<String> tempList = null;
while((line=br.readLine())!=null){
if(line.contains("<?xml version=\"1.0\"") || line.contains("<" + rootElement + ">") || line.contains("</" + rootElement + ">")){
continue;
}
if(line.contains("<"+ element +">")){
tempList = new ArrayList<String>();
}
tempList.add(line);
if(line.contains("</"+ element +">")){
if(hasConditions(tempList)){
writeToSplitFile(tempList);
writtenObjectCounter++;
totalCounter++;
}
}
if(writtenObjectCounter == itemsPerFile){
writtenObjectCounter = 0;
fileCounter++;
tempList.clear();
}
}
if(tempList.size() != 0){
writeClosingRootElement();
}
return totalCounter;
}
private void writeToSplitFile(List<String> itemList) throws Exception{
BufferedWriter wr = new BufferedWriter(new FileWriter(outputDirectory + File.separator + "split_" + fileCounter + ".xml", true));
if(writtenObjectCounter == 0){
wr.write("<" + rootElement + ">");
wr.write("\n");
}
for (String string : itemList) {
wr.write(string);
wr.write("\n");
}
if(writtenObjectCounter == itemsPerFile-1)
wr.write("</" + rootElement + ">");
wr.close();
}
private void writeClosingRootElement() throws Exception{
BufferedWriter wr = new BufferedWriter(new FileWriter(outputDirectory + File.separator + "split_" + fileCounter + ".xml", true));
wr.write("</" + rootElement + ">");
wr.close();
}
private boolean hasConditions(List<String> list){
int matchList = 0;
for (String condition : conditionList) {
for (String string : list) {
if(string.contains(condition)){
matchList++;
}
}
}
if(matchList >= conditionList.size()){
return true;
}
return false;
}
我知道每个写入的 staff 元素的打开/关闭流确实会影响性能。但是如果我每个文件写一次(其中可能包含 n 个staff)。自然地,根元素和拆分元素是可配置的。
有什么想法可以提高性能/逻辑吗?我更喜欢一些代码,但有时好的建议会更好
编辑:
这个 XML 示例实际上是一个虚拟示例,我尝试拆分的真正 XML 是拆分元素下大约 300-500 个不同的元素,它们都以随机顺序出现,并且数量各不相同。 Stax 可能不是最好的解决方案吗?
赏金更新:
我正在寻找一个解决方案(代码):
能够将 XML 文件拆分为 n 个带有 x 个拆分元素的部分(来自虚拟 XML 示例人员是拆分元素)。
被吐出的文件的内容应该被包裹在原始文件的根元素中(就像在虚拟示例公司中一样)
我希望能够指定必须在拆分元素中的条件,即我只想要有昵称的员工,我想丢弃那些没有昵称的员工。但是在运行无条件拆分时也可以无条件拆分。
代码不一定要改进我的解决方案(缺乏良好的逻辑和性能),但它可以工作。
并且对“但它有效”不满意。而且我找不到足够的 Stax 示例来进行此类操作,用户社区也不是很好。它也不必是 Stax 解决方案。
我可能要求太多了,但我来这里是为了学习东西,为我认为的解决方案提供丰厚的回报。
【问题讨论】:
-
我将添加一个关于在 vtd-xml 中执行此操作的新条目...比目前建议的任何解决方案都要好