我需要在文档中的一个级别重新排序大多数子节点。
该文档的结构看起来(简化)如下:
sheet
table
row
parameters
row
parameters
row
parameters
row
cell
header string
cell
header string
cell
header string
data row A
cell
data
cell
data
cell
data
data row B
cell
data
cell
data
cell
data
data row C
cell
data
cell
data
cell
data
data row D
cell
data
cell
data
cell
data
data row E
cell
data
cell
data
cell
data
row
parameters
row
parameters
row
parameters
row
parameters
row
parameters
我现在正在使用pugixml来加载,解析和遍历并访问大型xml文件,我最终会处理出一系列新的数据行。我知道我正确地解析了所有内容,查看重新排序的结果,我可以看到读取和处理是正确的。在我的所有优化和处理之后的重新排序解决方案是修订顺序中的标记列表,例如上面示例的{D,A,E,C,B}。所以现在我需要将它们重新排序到这个新的顺序,然后将生成的xml输出到一个新文件。实际数据大约为16兆,具有数百个数据元素行节点和每行超过一百个数据元素
我已经编写了一个例程来交换两个数据行,但我正在做的事情是在交换期间破坏xml结构一致性。我确定我不了解pugi移动节点和/或使节点句柄无效的方式。
我创建并保留节点句柄 - pugi :: xml_node - 到"表"级别节点,到#34;标题"行节点,以及"第一个数据"行节点,在上面的原始形式中将是节点"数据行A"。我知道这些句柄可以让我正确访问正确的数据 - 我可以在优化和重新排序计算期间暂停执行并查看它们,并检查行及其兄弟,并查看输入顺序。
"标题行"总是表的特定孩子,并且"第一个数据行"在"标题行"之后,它始终是兄弟姐妹。所以我在加载文件时检查它们并检查它们的数据一致性。
我对node :: insert_copy_before的理解是:
pugi:xml_node new_node_handle_in_document = parentnode.insert_copy_before( node_to_be_copied_to_child_of_parent , node_to_be_copied_nodes_next_sibling )
我的理解是,node_to_be_copied_to_child_of_parent包含所有子节点和属性的深度递归克隆将作为兄弟节点插入到node_to_be_copied_nodes_next_sibling之前,其中两者都是parentnode的子节点。
显然,如果node_to_be_copied_nodes_next_sibling也是"第一个数据行",那么第一个数据行的节点句柄在操作后仍然可能有效,但实际上不再是第一个数据的句柄节点。但是在文档上使用insert_copy会强制更新附近的 - 或不 - 更改的各个节点句柄吗?
所以,让我们看一下我试图开展工作的代码:
// a method to switch data rows
bool switchDataRows( int iRow1 , int iRow2 )
{
// temp vars
int iloop;
// navigate to the first row and create a handle that can move along siblings until we find the target
pugi::xml_node xmnRow1 = m_xmnFirstDataRow;
for ( iloop = 0 ; iloop < iRow1 ; iloop++ )
xmnRow1 = xmnRow1.next_sibling();
// navigate to the second row and create another handle that can move along siblings until we find the target
pugi::xml_node xmnRow2 = m_xmnFirstDataRow;
for ( iloop = 0 ; iloop < iRow2 ; iloop++ )
xmnRow2 = xmnRow2.next_sibling();
// ok.... so now get convenient handles on the the locations of the two nodes by creating handles to the nodes AFTER each
pugi::xml_node xmnNodeAfterFirstNode = xmnRow1.next_sibling();
pugi::xml_node xmnNodeAfterSecondNode = xmnRow2.next_sibling();
//此时我知道我创建的所有句柄都指向了预期的数据。
// now copy the second to the location before the first
pugi::xml_node xmnNewRow2 = m_xmnTableNode.insert_copy_before( xmnRow2 , xmnNodeAfterFirstNode );
//这里是我关注的地方。此副本是否按照我的要求执行操作,将第二个目标行的副本移动到表节点下的位置 //作为xmnNodeAfterFirstNode之前的孩子?如果是,那么此操作是否会使数据行节点的其他句柄无效?所有的赌注都是 //我们在兄弟姐妹列表中插入/复制之后,或者该子列表中其他节点的句柄是否仍然有效?
// now copy the first to the spot before the second
pugi::xml_node xmnNewRow1 = m_xmnTableNode.insert_copy_before( xmnRow1 , xmnNodeAfterSecondNode );
//显然,如果第一个insert_copy使数据行节点的其他句柄无效,那么这些句柄就不再有任何好处了......
// now delete the old rows
bool bDidRemoveRow1 = m_xmnTableNode.remove_child( xmnRow1 );
bool bDidRemoveRow2 = m_xmnTableNode.remove_child( xmnRow2 );
//这是我尝试在原始数据行节点被复制到新位置后删除
// we have to update the first data row!!!!!
bool bDidRowUpdate = updateFirstDataRow(); // a routine that starts with the header row node and finds the first sibling, the first data row
//和以前一样,如果使用insert_copy方法导致许多句柄移动,那么我将无法基于第一个数据行节点的更新&#34; //处理&#34;已知&#34;处理标题数据行节点。
// return the result
return( bDidRemoveRow2 && bDidRemoveRow1 && bDidRowUpdate );
}
正如我所说,这会破坏生成的xml的结构一致性。我可以保存它,但除了记事本之外什么都不会读。桌子最终有些乱码。如果我尝试使用自己的程序来阅读它,那么读者会报告一个&#34;元素不匹配&#34;错误并且拒绝加载它,这是可以理解的。
所以我做错了一件坏事。它们是什么?