したがって、Node オブジェクトの抽象構文ツリーがあります。各 Node には、任意の数の子ノードと、 std::map 構造を介して Node に添付された情報の一口である任意の数のタグがあります。ここで、構文ツリー全体を XML のような形式で出力したいと考えています。この目的のために、私はこの関数を使用します:
int __ostreamNode_indent = 0;
std::ostream & operator << ( std::ostream & ss, Node* n )
{
for( int i = 0 ; i < __ostreamNode_indent ; ++i )
ss << " ";
ss << "<" << n->getSymbolType() << " ";
for( std::map<std::string,std::string>::iterator itr = n->getTags().begin() ; itr != n->getTags().end() ; ++itr )
{
ss << itr->first << "=\"" << itr->second << "\" ";
}
ss << "numtags=" << n->getTags().size() << " ";
if( n->getChildren().size() == 0 )
ss << "/";
ss << ">" << std::endl;
__ostreamNode_indent++;
for( unsigned int i = 0 ; i != n->getChildren().size() ; ++i )
{
ss << n->getChildren().at(i);
}
__ostreamNode_indent--;
if( n->getChildren().size() != 0 )
{
for( int i = 0 ; i < __ostreamNode_indent ; ++i )
ss << " ";
ss << "</" << n->getSymbolType() << ">" << std::endl;
}
return ss;
}
構造はまさに私が望んでいた方法です。XML タグ タイプはノードのタイプであり、ノードのタグは同じ XML 開始タグに埋め込まれています。子ノードは、開始タグと終了タグの間に配置されます。次に例を示します。
<block line="0" numtags=2 >
<funcdef line="0" numtags=2 >
<identifier line="0" col="13" value="main" numtags=3 />
<expressionunion line="0" numtags=2 >
<identifier line="0" col="16" value="a" numtags=3 />
<identifier line="0" col="19" value="b" numtags=3 />
</expressionunion>
<assignment line="1" numtags=2 >
<identifier line="1" col="5" value="c" numtags=3 />
<numel line="1" numtags=2 >
<solveunder line="1" numtags=2 >
<identifier line="1" col="11" value="a" numtags=3 />
<identifier line="1" col="16" value="b" numtags=3 />
</solveunder>
</numel>
</assignment>
<return line="2" numtags=2 >
<power line="2" numtags=2 >
<identifier line="2" col="12" value="c" numtags=3 />
<identifier line="2" col="14" value="b" numtags=3 />
</power>
</return>
</funcdef>
</block>
この例も問題を示しています。すべてのタグを次の行で繰り返し処理します
for( std::map<std::string,std::string>::iterator itr = n->getTags().begin() ; itr != n->getTags().end() ; ++itr )
{
ss << itr->first << "=\"" << itr->second << "\" ";
}
key="value" として出力します。ただし、このループは最後の要素をスキップすることがあります。このループの直後の行がタグの数を出力する方法に注目してください。2 つのタグが存在する場合、最初のタグのみが実際に表示されます。2枚目が表示されないのはなぜですか?
編集:マークBが質問に答えました。何がうまくいかなかったのかについての正確な説明については、彼の答えを読んでください。彼は、これが getTags() の定義であると精神的に推測しました。
std::map<std::string,std::string> getTags()
{
return tags;
};
これに変更する(アンパサンドを追加する)とうまくいきました:
std::map<std::string,std::string> & getTags()
{
return tags;
};