Thanks to some good help from a previous post, I have been able to create
well formed xml as part of a report logger app. However, I still have a
small problem. When I add new xml to the log file, the new nodes are
appended to the original file. What I really want is for the log file to
grow as "report nodes" are added. Also, I am a bit concerned about
performance, particularly as the file grows in size. I must write to an xml
file (vs. a database) and am trying to understand the best way to do this. I
prefer to not use "temp files" and would like to just modify the log file
structure "in-place". Any advice is appreciated. Also, can anyone recommend
a good book that covers XML issues when programming with Managed VC++? The
reports I am generating will eventually be analyzed using Excel or some
other tools such as Crystal Reports.
The follow is a test app that illustrates the problem.
// This is the main project file for VC++ application project
// generated using an Application Wizard.
#include "stdafx.h"
#using <mscorlib.dll>
#using <System.dll>
#using <System.Xml.dll>
//
using namespace std;
using namespace System;
using namespace System::IO;
using namespace System::Text;
using namespace System::Xml;
int _tmain()
{
FileStream* fs;
XmlDocument* xmlReport;
// Test XML Snippet - emulates a test outcome
String* xmlStr = S"<TestResult><Name>Application Load
Test</Name><StartTime>21/05/2006
14:45:58:155</StartTime><StopTime>21/05/2006
14:46:35:530</StopTime><TestResult>FAIL</TestResult><TestAtoms><TestAtom><Name>RateTest
1</Name><StartTime>21/05/2006 14:46:20:530</StartTime><StopTime>21/05/2006
14:46:35:530</StopTime><TestResult>FAIL</TestResult><Duration>15</Duration><Direction>0</Direction><MinRate>255</MinRate><MaxRate>255</MaxRate></TestAtom></TestAtoms></TestResult>";
// the log file
String* sTestLogFile = S"D:\\Development\\LogTest\\ResultLog.xml";
//
try {
if(File::Exists(sTestLogFile) == true) {
// file already exist
fs = File::Open(sTestLogFile, FileMode::Open, FileAccess::ReadWrite,
FileShare::None);
xmlReport = new XmlDocument;
// Open from Stream
xmlReport->Load(fs);
XmlDocumentFragment* docFrag = xmlReport->CreateDocumentFragment();
docFrag->InnerXml = xmlStr;
XmlNode* ResultsNode =
xmlReport->DocumentElement->SelectSingleNode("TestResults");
// ResultsNode->AppendChild(docFrag);
ResultsNode->PrependChild(docFrag);
//xmlReport->DocumentElement->PrependChild(parentNode);
} else {
// no log file currently exist so we create a new file
fs = File::Open(sTestLogFile, FileMode::CreateNew, FileAccess::ReadWrite,
FileShare::None);
xmlReport = new XmlDocument();
XmlDeclaration* xmlDeclaration = xmlReport->CreateXmlDeclaration(S"1.0",
S"utf-8", NULL);
// Create the root element
XmlElement* rootNode = xmlReport->CreateElement("TestLog");
xmlReport->InsertBefore(xmlDeclaration, xmlReport->DocumentElement);
xmlReport->AppendChild(rootNode);
// Create a new <TestResults> element and add it to the root node
XmlElement* parentNode = xmlReport->CreateElement("TestResults");
xmlReport->DocumentElement->PrependChild(parentNode);
parentNode->InnerXml = xmlStr;
}
xmlReport->Save(fs);
fs->Close();
}
catch(XmlException* e)
{
String* msg = e->get_Message();
}
catch(Exception* e)
{
String* msg = e->get_Message();
}
return 0;
}
Output when no file exist GOOD:!
<?xml version="1.0" encoding="utf-8"?>
<TestLog>
<TestResults>
<TestResult>
<Name>Application Load Test</Name>
<StartTime>21/05/2006 14:45:58:155</StartTime>
<StopTime>21/05/2006 14:46:35:530</StopTime>
<TestResult>FAIL</TestResult>
<TestAtoms>
<TestAtom>
<Name>RateTest 1</Name>
<StartTime>21/05/2006 14:46:20:530</StartTime>
<StopTime>21/05/2006 14:46:35:530</StopTime>
<TestResult>FAIL</TestResult>
<Duration>15</Duration>
<Direction>0</Direction>
<MinRate>255</MinRate>
<MaxRate>255</MaxRate>
</TestAtom>
</TestAtoms>
</TestResult>
</TestResults>
</TestLog>
Output when file exist (see above) BAD!
<?xml version="1.0" encoding="utf-8"?>
<TestLog>
<TestResults>
<TestResult>
<Name>Application Load Test</Name>
<StartTime>21/05/2006 14:45:58:155</StartTime>
<StopTime>21/05/2006 14:46:35:530</StopTime>
<TestResult>FAIL</TestResult>
<TestAtoms>
<TestAtom>
<Name>RateTest 1</Name>
<StartTime>21/05/2006 14:46:20:530</StartTime>
<StopTime>21/05/2006 14:46:35:530</StopTime>
<TestResult>FAIL</TestResult>
<Duration>15</Duration>
<Direction>0</Direction>
<MinRate>255</MinRate>
<MaxRate>255</MaxRate>
</TestAtom>
</TestAtoms>
</TestResult>
</TestResults>
</TestLog><?xml version="1.0" encoding="utf-8"?>
<TestLog>
<TestResults>
<TestResult>
<Name>Application Load Test</Name>
<StartTime>21/05/2006 14:45:58:155</StartTime>
<StopTime>21/05/2006 14:46:35:530</StopTime>
<TestResult>FAIL</TestResult>
<TestAtoms>
<TestAtom>
<Name>RateTest 1</Name>
<StartTime>21/05/2006 14:46:20:530</StartTime>
<StopTime>21/05/2006 14:46:35:530</StopTime>
<TestResult>FAIL</TestResult>
<Duration>15</Duration>
<Direction>0</Direction>
<MinRate>255</MinRate>
<MaxRate>255</MaxRate>
</TestAtom>
</TestAtoms>
</TestResult>
<TestResult>
<Name>Application Load Test</Name>
<StartTime>21/05/2006 14:45:58:155</StartTime>
<StopTime>21/05/2006 14:46:35:530</StopTime>
<TestResult>FAIL</TestResult>
<TestAtoms>
<TestAtom>
<Name>RateTest 1</Name>
<StartTime>21/05/2006 14:46:20:530</StartTime>
<StopTime>21/05/2006 14:46:35:530</StopTime>
<TestResult>FAIL</TestResult>
<Duration>15</Duration>
<Direction>0</Direction>
<MinRate>255</MinRate>
<MaxRate>255</MaxRate>
</TestAtom>
</TestAtoms>
</TestResult>
</TestResults>
</TestLog>