ドキュメント内の 1 つのレベルで、大部分の子ノードの順序を変更する必要があります。
ドキュメントの構造は (簡略化して) 次のようになります。
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 メガバイトで、数百のデータ要素行ノードと、各行に 100 以上のデータ要素があります。
2 つのデータ行をスワップするルーチンを作成しましたが、スワップ中に xml 構造の一貫性を破壊しています。pugiがノードを移動したり、ノードハンドルを無効にしたりする方法を理解していないと確信しています。
ノード ハンドル -- pugi::xml_node -- を作成して、「テーブル」レベル ノード、「ヘッダー」行ノード、および「最初のデータ」行ノード (上記の元の形式ではノード) に設定します。 「データ行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 の直前に兄弟として挿入されるということです。
明らかに、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 );
// ここから私の懸念が始まります。このコピーは、2 番目のターゲット行のコピーを表ノードの下の位置に移動し、// 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 メソッドを使用した結果、多くのハンドルが動き回った場合、「最初のデータ行ノード」の更新に基づいて // ヘッダーへの「既知の」ハンドルに基づいて処理することはできませんデータ行ノード。
// return the result
return( bDidRemoveRow2 && bDidRemoveRow1 && bDidRowUpdate );
}
私が言ったように、これは結果の xml の構造的な一貫性を破壊します。保存できますが、メモ帳以外は何も読み取れません。テーブルが少し文字化けしてしまいます。独自のプログラムを使用して読み取ろうとすると、当然のことながら、リーダーは「要素の不一致」エラーを報告し、読み込みを拒否します。
だから私は1つ以上のことを間違っています。彼らは何ですか?