1

Xerces-cをラップするArabicaを使用してXMLを解析しています。以下のサンプルコードは、.getNodeName()メソッドを使用すると正しい名前を返しますが、.getNodeValue()メソッドを使用すると正しい値を返しません。

bool readXML(bfs::path xmlfullfile) 
{
  // first check to see if the file exists
  if (!bfs::is_regular_file(xmlfullfile)) return false;

  Arabica::SAX2DOM::Parser<std::string> domParser;
  Arabica::SAX::CatchErrorHandler<std::string> eh;
  Arabica::DOM::Document<std::string> xmlDoc; 
  Arabica::SAX::InputSource<std::string> is;

  domParser.setErrorHandler(eh);
  is.setSystemId(xmlfullfile.string());
  domParser.parse(is);

  if(!eh.errorsReported()) 
  {
    xmlDoc = domParser.getDocument();
    xmlDoc.normalize();

    Arabica::DOM::NodeList<string_type> objects = xmlDoc.getElementsByTagName("object");
    for (size_t t = 0; t < objects.getLength(); t++) 
    {
      Arabica::DOM::Node<std::string> object = objects.item(t);
      Arabica::DOM::NodeList<std::string> values = object.getChildNodes(); 
      for (size_t u = 0; u < values.getLength(); u++) 
      {
        values.item(u).normalize(); 
        string name = values.item(u).getNodeName(); 
        string val = values.item(u).getNodeValue(); 
        cout << "Node streaming = \"" << values.item(u) << "\", meaning that name = \"" << name << "\" and value = \"" << val << "\"" << endl; 
      }
    }
    return true;
  } else {
    std::cerr << eh.errors() << std::endl;
    eh.reset();
    return false;
  }
}

私が解析しようとしているサンプルXMLは次のとおりです。

<annotation>
    <filename>1a.jpg</filename>
    <folder>Sample</folder>
    <source>
        <database>Some database</database>
        <annotation>Annotator</annotation>
        <image>Some source</image>
    </source>
    <size>
        <width>3264</width>
        <height>1840</height>
        <depth>0</depth>
    </size>
    <segmented>0</segmented>
    <object>
        <name>somename</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <occluded>0</occluded>
        <bndbox>
            <xmin>48</xmin>
            <ymin>671</ymin>
            <xmax>3213</xmax>
            <ymax>1616</ymax>
        </bndbox>
    </object>
</annotation>

出力は次のようになります。

Node streaming = "
                ", meaning that name = "#text" and value = "
                "
Node streaming = "<name>somename</name>", meaning that name = "name" and value = ""
Node streaming = "
                ", meaning that name = "#text" and value = "
                "
Node streaming = "<pose>Unspecified</pose>", meaning that name = "pose" and valu
e = ""
Node streaming = "
                ", meaning that name = "#text" and value = "
                "
Node streaming = "<truncated>0</truncated>", meaning that name = "truncated" and
 value = ""
Node streaming = "
                ", meaning that name = "#text" and value = "
                "
Node streaming = "<difficult>0</difficult>", meaning that name = "difficult" and
 value = ""
Node streaming = "
                ", meaning that name = "#text" and value = "
                "
Node streaming = "<occluded>0</occluded>", meaning that name = "occluded" and va
lue = ""
Node streaming = "
                ", meaning that name = "#text" and value = "
                "
Node streaming = "<bndbox>
                        <xmin>48</xmin>
                        <ymin>671</ymin>
                        <xmax>3213</xmax>
                        <ymax>1616</ymax>
                </bndbox>", meaning that name = "bndbox" and value = ""
Node streaming = "
        ", meaning that name = "#text" and value = "
        "

何が間違っているのかよくわかりません。getNodeName()は正しい名前を返すので(もちろん#textでない場合)、getNodeValue()が何も返さないという事実は私に不思議に思います。

4

2 に答える 2

1

空白のみのテキストノードもカウントしています。その場所にテキストノードを許可しないDTDを追加すると役立つ場合があります。非検証パーサーは、すべての空白ノードを報告する必要があり、無視できるものとそうでないものを想定することはできません。

結論として、空白のテキストノードを削除したい場合は、DOMプログラムで自分でプログラムする必要があります。

于 2013-01-11T10:13:07.350 に答える
0

コードを他のXMLライブラリと比較した後、解決策を見つけました。明らかに、ノードの値は単純なテキストフィールドではなく、テキスト値にアクセスできるようにするには、その単純なリーフノードの最初の子を取得する必要があります。私のやり方が最善の方法かどうかはわかりませんが、他の誰かが同じ問題を抱えている場合のコードは次のとおりです。

for (size_t u = 0; u < values.getLength(); u++) 
{
  string name = values.item(u).getNodeName();
  if (name == "#text") continue;
  string val = values.item(u).getFirstChild().getNodeValue(); 
  cout << "Node streaming = \"" << values.item(u) << "\", meaning that name = \"" << name << "\" and value = \"" << val << "\"" << endl; 
}

注:実動コードでは、すべてのノードが単純なリーフノードであるとは限らないという事実を考慮に入れる必要があります。したがって、私のコードはソリューションの半分にすぎません。

于 2012-12-28T21:03:29.210 に答える