letanphuc / pugixml

Automatically exported from code.google.com/p/pugixml
0 stars 0 forks source link

Node value #208

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hi,

I am using pugi to parse and create XML documents.
While retrieving the child nodes if node has value, it is showing Bad Ptr for 
value. And if i expand that node while debuging, it is showing node value for 
first child of that node. ANd bad ptr for name(for first child).

If i retrieve the node value separately it is returning correctly. 

Thanks,
Kshitija Choudhary

Original issue reported on code.google.com by kshitija...@gmail.com on 5 Jul 2013 at 6:05

GoogleCodeExporter commented 9 years ago
This is how it should be. Let's review:

<node>value</node> is represented as:

1. xml_node with type() == node_element, name() == "node" and value() == "" 
(value pointer that the debugger shows you is NULL)
2. this node has a child, xml_node with type() == node_pcdata, name() == "" 
(name pointer that the debugger shows you is NULL) and value() == "value"

As a reminder, you can use child_value() to get the value of the child node 
directly, or, starting with pugixml 1.2, you can use node.text()

The expectation that <node>value</node> is represented by 1 node with name() == 
"node" and value() == "value" is *incorrect*. It does not work with more 
complicated cases such as <node>value1<child/>value2</node>.

Original comment by arseny.k...@gmail.com on 8 Jul 2013 at 4:26

GoogleCodeExporter commented 9 years ago
I am tring to append a child to node.
Creating child node in document. (xmldoc.append_child()).
Then appending this new child to node. But when i expand the node it is showing 
the newly appended node as previous siblink of the node instead of first child.

Original comment by kshitija...@gmail.com on 9 Jul 2013 at 12:37

GoogleCodeExporter commented 9 years ago
Please provide the code that you're using. Also note that prev_sibling_c value 
in debugger can be confusing because of some memory optimization pugixml is 
doing - you should only rely on whatever previous_sibling() and the like return.

Original comment by arseny.k...@gmail.com on 9 Jul 2013 at 2:55

GoogleCodeExporter commented 9 years ago
For creating new node in document i am using following code:
XmlDocument is class which handles document.
XmlDocument::CreateElement(const std::wstring& name, XmlNode& element) 
{

   bool setName;
   pugi::xml_node tempNode;

   pugi::xml_node node;// = new pugi::xml_node;

   //Convert wstring to pugi::char_t*   
   std::string strName = CDSCopyWideCharToChar(name);
   const pugi::char_t* bstr_name = strName.c_str();  

    if(NULL == m_XmlNode)
    {
        return OK;
    }

   //Create new element 
    tempNode = m_XmlDocument.append_child(pugi::node_element);

   //if element node created is null then fail.
   if(NULL == tempNode)
   {
      return error;
   }

   //Give name to the new element created
   setName = tempNode.set_name(bstr_name);
   if(setName == FALSE)
   {
       return error;
   }
   element.m_XmlNode = tempNode;

   m_XmlDocument.remove_child(tempNode);
   return ok;
}

Following function is used to append the node created in above function. 
XmlNode::AppendChildNode(XmlNode& child)
{
   pugi::xml_node childNode;
   pugi::xml_attribute findAttribute, setAttribute;
   const pugi::char_t* findAttrName;
   const pugi::char_t* nodeName;
   const pugi::char_t* nodeValue;

   //check if node is null then fail
   if(NULL == m_XmlNode)
   {
      return error;
   }
      nodeName = child.m_XmlNode.name();
   nodeValue = child.m_XmlNode.text().get();
   //append node with child name
 //  childNode = m_XmlNode.append_child(nodeName);      
   childNode = m_XmlNode.append_child(pugi::node_element);
   childNode.set_name(nodeName);
   //childNode.text().set(child.m_XmlNode.text().get());
   if(nodeValue != "")
      childNode.append_child(pugi::node_pcdata).set_value(nodeValue);

   //append attributes to the appended node
   findAttribute = child.m_XmlNode.first_attribute();
   for(pugi::xml_attribute_iterator it = child.m_XmlNode.attributes_begin(); it != child.m_XmlNode.attributes_end(); it++)
   {
      findAttrName = findAttribute.name();
      setAttribute = childNode.append_attribute(findAttrName);
      setAttribute.set_value(findAttribute.value());
      findAttribute = findAttribute.next_attribute();
   }
   child.m_XmlNode = childNode;

   //check appended node is null, if yes then fail
   if(NULL == childNode)
   {
       return error;
   }

   return ok;
}

Original comment by kshitija...@gmail.com on 10 Jul 2013 at 5:23

GoogleCodeExporter commented 9 years ago
   element.m_XmlNode = tempNode;
   m_XmlDocument.remove_child(tempNode);

This code is invalid. remove_child() invalidates the value of tempNode - any 
subsequent use of tempNode will be invalid.

It looks like you're trying to use an approach where you first create 
free-standing XML nodes and then insert them in particular place in XML 
document. pugixml does not work like that - in pugixml, you have to do both 
(create and insert) at the same time, which is what append_child() and the like 
do.

Original comment by arseny.k...@gmail.com on 10 Jul 2013 at 5:52

GoogleCodeExporter commented 9 years ago
But i have to keep the sequence as it is. i.e.first create free-standing XML 
nodes and then insert them in particular place in XML document.
Then what will be the solution?

Original comment by kshitija...@gmail.com on 10 Jul 2013 at 6:06

GoogleCodeExporter commented 9 years ago
This workflow is not recommended in pugixml. If you don't have a choice, the 
only working solution is to *copy* a node to the target place - essentially the 
same thing that you're doing, except that you can just use something like 
m_XmlNode.append_copy(child.m_XmlNode).

Note that for this to work the original node has to still exist in some 
document - you can't remove it right after creation. You can use an extra 
xml_document for that, however - you don't have to keep these nodes in the same 
document as the one you're copying them to.

Original comment by arseny.k...@gmail.com on 10 Jul 2013 at 6:19

GoogleCodeExporter commented 9 years ago
I have tried with both the options you suggested. But no success.
With append_copy() or append_child(), if i print the xml on node it 
Succeeds(node.print()). Shows correct xml.
e.g.
<node>
<childnode/>
</node>

But if I print xml on document(doc.print) it prints as
<node></node>

Original comment by kshitija...@gmail.com on 12 Jul 2013 at 12:42

GoogleCodeExporter commented 9 years ago
With append_copy() problem is solved.

If i use xml like
<node>nodevalue2</node> and try to retrieve the node value it returns 
"nodevalue2"
But if I use xml lik:
<node>
    nodevalue2
</node>
and try to retrieve the node value it returns "    nodevalue2".
I am using node.text().get() to retrieve the value.
How to resolve this?

Original comment by kshitija...@gmail.com on 17 Jul 2013 at 10:37

GoogleCodeExporter commented 9 years ago
There is no built-in support for trimming whitespace from PCDATA during 
parsing. You'll have to trim whitespace yourself (you can refer to 
http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring)

Original comment by arseny.k...@gmail.com on 20 Jul 2013 at 6:05

GoogleCodeExporter commented 9 years ago

Original comment by arseny.k...@gmail.com on 30 Jul 2013 at 12:34