I am newbie to xml and xslt area. I have written simple COM utility to transform xsl using xslt. But is failing at transformNodeToObject function call. I am using visual studio 15.
As you can see i am using the msxml6.dll import.
There was another type of call m_hrDOMInitStatus = CoCreateInstance(MSXML2::CLSID_DOMDocument60, NULL, CLSCTX_INPROC_SERVER, MSXML2::IID_IXMLDOMDocument3, (void**)&m_pDoc); Not sure whether i need to use this API
#include "stdafx.h"
#include <windows.h>
#include "iostream"
#include <WTypes.h>
#include <comdef.h>
#include <wchar.h>
#include <vector>
#import <msxml6.dll>
using namespace MSXML2;
using namespace std;
int main()
{
HRESULT hResult = S_OK;
hResult = CoInitialize(NULL);
if (FAILED(hResult))
{
cerr << "Failed to initialize COM environment" << endl;
return 0;
}
// MSXML COM smart pointers
// Use the Document2 class to enable schema validation
IXMLDOMDocument2Ptr spDocSource;
IXMLDOMDocument2Ptr spDocResult;
IXMLDOMDocument2Ptr spDocStylesheet;
struct IDispatch * pDispatch;
// Create the COM DOM Document objects
hResult = spDocSource.CreateInstance(__uuidof(DOMDocument60));
if FAILED(hResult)
{
cerr << "Failed to create Source Document instance" << endl;
return 1;
}
hResult = spDocResult.CreateInstance(__uuidof(DOMDocument60));
if FAILED(hResult)
{
cerr << "Failed to create Result Document instance" << endl;
return 1;
}
hResult = spDocStylesheet.CreateInstance(__uuidof(DOMDocument60));
if FAILED(hResult)
{
cerr << "Failed to create Stylesheet Document instance" << endl;
return 1;
}
// Load the source document
spDocSource->async = VARIANT_FALSE;
hResult = spDocSource->load("xmlinputfile.xml");
if (hResult != VARIANT_TRUE)
{
cout << "Error parsing xmlinputfile.xml" << endl;
return 1;
}
spDocSource->async = VARIANT_FALSE;
hResult = spDocSource->load("XSLTFile1.xslt");
if (hResult != VARIANT_TRUE)
{
cout << "Error parsing XSLTFile1.xml" << endl;
return 1;
}
spDocResult->QueryInterface(IID_IDispatch, (void **)&pDispatch);
VARIANT vResultDoc;
vResultDoc.vt = VT_DISPATCH;
vResultDoc.pdispVal = pDispatch;
hResult = spDocSource->transformNodeToObject(spDocStylesheet, vResultDoc);
if FAILED(hResult)
{
cout << "Error in performing transformation" << endl;
return 1;
}
return 0;
}
xml input:
_____________
<?xml version="1.0"?>
-<MODEL-LIST ENTERPRISE-XML-VERSION="3">
<MODEL TYPE="Enhanced Macrocell" ID="450 MHz Default"> </MODEL>
</MODEL-LIST>
xslt:
----
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<MODEL-LIST>
<xsl:for-each select="MODEL">
<xsl:element name="MODEL">
<xsl:attribute name="ID">
<xsl:value-of select="#ID"/>
</xsl:attribute>
<xsl:attribute name="TYPE">
<xsl:value-of select="#TYPE"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</MODEL-LIST>
</xsl:template>
</xsl:stylesheet>
The Microsoft online examples on using MSXML with smart pointers, like https://msdn.microsoft.com/en-us/ie/ms766389(v=vs.100), suggest that the call to transformNode would simply work as spDocSource->transformNodeToObject(spDocStylesheet, spDocResult.GetInterfacePtr()).
I think this is due to KB of CVE-2019-1357.
Does the phenomenon not stop when the following KB is uninstalled?
KB4522007: Windows 7 SP1/8.1/ServerR2 SP1/2012(IE10/IE11)/2012 R2/2008 SP2(IE9)
KB4522009: Windows 10(RTM、build10240)
KB4522010: Windows 10 ver1607/Server 2016
KB4522011: Windows 10 ver1703
KB4522012: Windows 10 ver1709
KB4522014: Windows 10 ver1803
KB4522015: Windows 10 ver1809/Server 2019
KB4522016: Windows 10 ver1903
Related
I would like to validate an XML file in C++ using the MSXML6 parser and have followed the instructions on http://msdn.microsoft.com/en-us/library/ms762774%28v=vs.85%29.aspx . However, the project I'm working on requires the XSD schema to be embedded in the binary file.
This is the XML file, which should be validated (all files simplified for demonstration purposes):
<?xml version="1.0" encoding="UTF-8"?>
<Document xsi:schemaLocation="urn:test schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:test">
<Party>
<Id>1</Id>
<Name>Bob</Name>
<Salary>100.00</Salary>
</Party>
<Party>
<Id>2</Id>
<Name>Alice</Name>
<Salary>200.00</Salary>
</Party>
<Party>
<Id>3</Id>
<Name>Günther</Name>
<Salary>300.00</Salary>
</Party>
</Document>
And here's the XSD schema:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<xs:schema xmlns="urn:test" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:test" elementFormDefault="qualified">
<xs:simpleType name="NameType">
<xs:restriction base="xs:string">
<xs:pattern value="([A-Za-z0-9ÄÖÜäöü]){1,10}"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="PartyType">
<xs:sequence>
<xs:element name="Id" type="xs:integer"/>
<xs:element name="Name" type="NameType"/>
<xs:element name="Salary" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Document">
<xs:complexType>
<xs:choice minOccurs="1" maxOccurs="9999999">
<xs:element name="Party" type="PartyType"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
The above XSD schema is embedded as a Win32 resource in the executable and can be referenced via the identifier "IDR_XSDSCHEMA1" (see comment line with OPTION 1):
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#import <msxml6.dll>
#include "resource.h"
// Macro that calls a COM method returning HRESULT value.
#define CHK_HR(stmt) do { hr=(stmt); if (FAILED(hr)) return bstrResult; } while(0)
//Method for acquiring own handle
HMODULE GetThisDllHandle()
{
MEMORY_BASIC_INFORMATION info;
size_t len = VirtualQueryEx(GetCurrentProcess(), (void*)GetThisDllHandle, &info, sizeof(info));
return len ? (HMODULE)info.AllocationBase : NULL;
}
_bstr_t validateFile(_bstr_t bstrFile)
{
//Schema collection
MSXML2::IXMLDOMSchemaCollectionPtr pXS;
//XML document
MSXML2::IXMLDOMDocument2Ptr pXD;
//XSD document
MSXML2::IXMLDOMDocument2Ptr pXSD;
//Validation object
MSXML2::IXMLDOMParseErrorPtr pErr;
_bstr_t bstrResult = L"";
HRESULT hr = S_OK;
//Load XSD schema from resource
HMODULE handle = GetThisDllHandle();
HRSRC rc = ::FindResource(handle, MAKEINTRESOURCE(IDR_XSDSCHEMA1), L"XSDSCHEMA");
HGLOBAL rcData = ::LoadResource(handle, rc);
LPVOID data = (::LockResource(rcData));
::FreeResource(rcData);
//Load schema stream into document
CHK_HR(pXSD.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER));
if (pXSD->loadXML((LPCSTR)data) != VARIANT_TRUE)
return bstrResult;
// Create a schema cache
CHK_HR(pXS.CreateInstance(__uuidof(MSXML2::XMLSchemaCache60), NULL, CLSCTX_INPROC_SERVER));
//--> OPTION 1: VALIDATING AGAINST EMBEDDED XSD RESOURCE; DOESN'T WORK <--
CHK_HR(pXS->add(L"urn:test", pXSD.GetInterfacePtr()));
//--> OPTION 2: VALIDATING AGAINST PHYSICAL XSD FILE; WORKS FINE <--
//CHK_HR(pXS->add(L"urn:test", L"schema.xsd"));
// Create a DOMDocument and set its properties.
CHK_HR(pXD.CreateInstance(__uuidof(MSXML2::DOMDocument60), NULL, CLSCTX_INPROC_SERVER));
pXD->async = VARIANT_FALSE;
pXD->validateOnParse = VARIANT_TRUE;
pXD->preserveWhiteSpace = VARIANT_TRUE;
//Assign the schema cache to the Document's schema collection
pXD->schemas = pXS.GetInterfacePtr();
//Load XML file
if(pXD->load(bstrFile) != VARIANT_TRUE)
{
pErr = pXD->parseError;
bstrResult = _bstr_t(L"Validation failed on ") + bstrFile +
_bstr_t(L"\n=====================") +
_bstr_t(L"\nReason: ") + _bstr_t(pErr->Getreason()) +
_bstr_t(L"\nSource: ") + _bstr_t(pErr->GetsrcText()) +
_bstr_t(L"\nLine: ") + _bstr_t(pErr->Getline());
}
else
{
bstrResult = _bstr_t(L"Validation succeeded for ") + bstrFile +
_bstr_t(L"\n======================\n") +
_bstr_t(pXD->xml);
}
return bstrResult;
}
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = CoInitialize(NULL);
if(SUCCEEDED(hr))
{
try
{
_bstr_t bstrOutput = validateFile(L"Document.xml");
MessageBox(NULL, bstrOutput, L"schemaCache",MB_OK);
}
catch(_com_error &e)
{
MessageBox(NULL, e.Description(), L"schemaCache",MB_OK);
}
CoUninitialize();
}
return 0;
}
Unfortunately, I have encountered some strange behavior while trying to run the validation routine (OPTION 1 comment). It seems, that the umlauts in the XSD resource aren't properly decoded while being loaded into the stream. This results in a messed up validation reference, as seen in the following result:
However, when the schema file is loaded directly from disk (OPTION 2 comment), the validation routine runs just fine:
I have already tried to convert the loaded stream from Unicode to Multi-Byte and vice versa, however to no avail. Is there something I'm missing here? Or are Win32 resources limited to a specific character set? Thanks for any suggestions.
See comment from WhozCraig: Using MultiByteToWideChar() with CP_UTF8 as an input argument returns a valid Unicode string.
For some reason I can not read data from a xml file properly.
For example instead of "Schrüder" I get something like "Schrüder".
My code:
tinyxml2::XMLDocument doc;
bool open(string path) {
if(doc.LoadFile(path.c_str()) == XML_SUCCESS)
return true;
return false;
}
int main() {
if(open("C:\\Users\\Admin\\Desktop\\Test.xml"))
cout << "Success" << endl;
XMLNode * node = doc.RootElement();
string test = node->FirstChild()->GetText();
cout << test << endl;
return 0;
}
Part of XML:
<?xml version="1.0" encoding="UTF-8"?>
<myXML>
<my:TXT_UTF8Test>Schrüder</my:TXT_UTF8Test>
</myXML>
Notice that if I convert it to ANSI and change the encoding type to "ISO-8859-15" it works fine.
I read that something like "LoadFile( filename, TIXML_ENCODING_UTF8 )" should help. However that's not the case (error: Invalid arguments, it just expects a const char). I have the latest version of TinyXML2 (I guess?). I downloaded it just a couple minutes ago from https://github.com/leethomason/tinyxml2.
Any ideas?
Edit: When I write the string to a .xml or .txt file it works fine. There might be some problem with the eclipse ide console. Anyway, when I try to send the string via E-Mail, I also get the same problems. Here's the MailSend script:
bool sendMail(std::string params) {
if( (int) ShellExecute(NULL, "open", "H:\\MailSend\\MailSend_anhang.exe", params.c_str(), NULL, SW_HIDE) <= 32 )
return false;
return true;
}
I call it in the main method like this:
sendMail("-f:d.nitschmann#example.com -t:person2#example.com -s:Subject -b:Body " + test);
I think the problem is with your terminal; can you try run your test code in a different terminal ? one with known good UTF-8 support ?
Output with terminal in UTF-8 mode:
$ ./a.out
Success
Schrüder
Output with terminal in ISO-8859-15 mode:
$ ./a.out
Success
SchrÃŒder
Also - please try and follow http://sscce.org/ - for posterity sake here is your code with everything needed to compile (17676169.cpp):
#include <tinyxml2.h>
#include <string>
#include <iostream>
using namespace std;
using namespace tinyxml2;
tinyxml2::XMLDocument doc;
bool open(string path) {
if(doc.LoadFile(path.c_str()) == XML_SUCCESS)
return true;
return false;
}
int main() {
if(open("Test.xml"))
cout << "Success" << endl;
XMLNode * node = doc.RootElement();
string test = node->FirstChildElement()->GetText();
cout << test << endl;
return 0;
}
compiled with:
g++ -o 17676169 17676169.cpp -ltinyxml2
and uuencoded Test.xml - to ensure exact same data is used
begin 660 Test.xml
M/#]X;6P#=F5R<VEO;CTB,2XP(B!E;F-O9&EN9STB551&+3#B/SX*/&UY6$U,
M/#H#("`#/&UY.E185%]55$8X5&5S=#Y38VARP[QD97(\+VUY.E185%]55$8X
/5&5S=#X*/"]M>5A-3#X*
`
end
Edit 1:
If you want to confirm this theory - run this in eclipse:
#include <iostream>
#include <string>
#include <fstream>
int main()
{
std::ifstream ifs("Test.xml");
std::string xml_data((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
std::cout << xml_data;
}
Output with terminal in UTF-8 mode:
$ ./17676169.cat
<?xml version="1.0" encoding="UTF-8"?>
<myXML>
<my:TXT_UTF8Test>Schrüder</my:TXT_UTF8Test>
</myXML>
Output with terminal in ISO-8859-15 mode:
$ ./17676169.cat
<?xml version="1.0" encoding="UTF-8"?>
<myXML>
<my:TXT_UTF8Test>SchrÃŒder</my:TXT_UTF8Test>
</myXML>
I've been playing with gSOAP XML data binding by loading XML document into C++ class, modifying data and serializing it back into XML.
Here's the snippet of the XML - library.xml:
<?xml version="1.0" encoding="UTF-8"?>
<gt:Library xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:gt="http://www.bk.com/gSOAP/test">
<gt:Books>
<gt:Book isbn="0132350882" author="Robert C. Martin" title="Clean Code">
<gt:CopiesAvailable>2</gt:CopiesAvailable>
</gt:Book>
<gt:Book isbn="020161622X" author="Andrew Hunt" title="The Pragmatic Programmer">
<gt:CopiesAvailable>0</gt:CopiesAvailable>
</gt:Book>
<gt:Book isbn="0201633612" author="Erich Gamma" title="Design patterns">
<gt:CopiesAvailable>1</gt:CopiesAvailable>
</gt:Book>
</gt:Books>
...
</gt:Library>
The following code loads XML into object, modifies object and serializes it back into XML.
Note that XML is loaded from a file, via file stream and that data to be added is obtained from a user, via stdin (cin).
main.cpp:
#include "soapH.h"
#include "gt.nsmap"
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using std::cin;
using std::cout;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::fstream;
using std::string;
using std::stringstream;
void DisplayAllBooks(const _gt__Library& library)
{
cout << "\n\nDisplaying all books in the library:" << endl;
std::vector<_gt__Library_Books_Book>::const_iterator it = library.Books.Book.begin();
for(;it != library.Books.Book.end(); it++)
{
cout << "\nBook:\n" << "\tTitle:" << (*it).title << "\n\tAuthor:" << (*it).author <<"\n\tISBN: " << (*it).isbn << "\n\tCopies available: " << static_cast<int>((*it).CopiesAvailable) << endl;
}
}
void AddBook(_gt__Library& library)
{
cout << "\n\nAdding a new book:" << endl;
_gt__Library_Books_Book book;
cout << "\tTitle: " << std::flush;
getline(cin, book.title);
cout << "\tAuthor: " << std::flush;
getline(cin, book.author);
cout << "\tISBN:" << std::flush;
getline(cin, book.isbn);
cout << "\tCopies available: " << std::flush;
string strCopiesAvailable;
getline(cin, strCopiesAvailable);
stringstream ss(strCopiesAvailable);
ss >> book.CopiesAvailable;
library.Books.Book.push_back(book);
}
// Terminate and destroy soap
void DestroySoap(struct soap* pSoap)
{
// remove deserialized class instances (C++ objects)
soap_destroy(pSoap);
// clean up and remove deserialized data
soap_end(pSoap);
// detach context (last use and no longer in scope)
soap_done(pSoap);
}
int main()
{
//
// Create and intialize soap
//
// gSOAP runtime context
struct soap soap;
// initialize runtime context
soap_init(&soap);
// Set input mode
soap_imode(&soap, SOAP_ENC_XML);
// reset deserializers; start new (de)serialization phase
soap_begin(&soap);
//
// Load XML (Deserialize)
//
_gt__Library library;
string strXML = "library.xml";
ifstream fstreamIN(strXML);
soap.is = &fstreamIN;
// calls soap_begin_recv, soap_get__gt__Library and soap_end_recv
if(soap_read__gt__Library(&soap, &library) != SOAP_OK)
{
std::cout << "soap_read__gt__Library() failed" << std::endl;
DestroySoap(&soap);
return 1;
}
fstreamIN.close();
//
// Display books before and after adding a new book
//
DisplayAllBooks(library);
AddBook(library);
DisplayAllBooks(library);
//
// Serialize
//
soap_set_omode(&soap, SOAP_XML_INDENT);
ofstream fstreamOUT("library.xml");
soap.os = &fstreamOUT;
// calls soap_begin_send, soap_serialize, soap_put and soap_end_send
if(soap_write__gt__Library(&soap, &library) != SOAP_OK)
{
std::cout << "soap_write__gt__Library() failed" << std::endl;
DestroySoap(&soap);
return 1;
}
fstreamOUT.close();
DestroySoap(&soap);
return 0;
}
After running this test application, everything is fine apart from all newly added elements have strings that terminate with a Carriage Return character (CR -
):
Modified XML looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<gt:Library xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:gt="http://www.bk.com/gSOAP/test">
<gt:Books>
<gt:Book isbn="0132350882" author="Robert C. Martin" title="Clean Code">
<gt:CopiesAvailable>2</gt:CopiesAvailable>
</gt:Book>
<gt:Book isbn="020161622X" author="Andrew Hunt" title="The Pragmatic Programmer">
<gt:CopiesAvailable>0</gt:CopiesAvailable>
</gt:Book>
<gt:Book isbn="0201633612" author="Erich Gamma" title="Design patterns">
<gt:CopiesAvailable>1</gt:CopiesAvailable>
</gt:Book>
<gt:Book isbn="12345678
" author="Scott Meyers
" title="Effective C++
">
<gt:CopiesAvailable>123</gt:CopiesAvailable>
</gt:Book>
</gt:Books>
...
</gt:Library>
I traced the source of the bug and found the following:
soap_read__gt__Library() calls soap_begin_send() which executes the following line:
_setmode(soap->recvfd, _O_BINARY);
soap->recvfd is set to 0 in soap_init() and 0 is a value of file descriptor of stdin.
Once stdin's mode is changed to a binary, STL library does not parse \r\n to a single \n for read operations and getline(cin, str), as usual, reads everything up to \n, copying \r into output string. And that is exactly Carriage Return character which appears in new strings in the final XML.
My question is: Why does gSOAP modify stdin mode if the data source is a file stream? Is this a bug in gSOAP?
NOTE:
As expected, if stdio's mode is reverted back to _O_TEXT after soap_begin_send() but before reading data from std::cin, getline() works fine. Here is the patch:
_setmode(_fileno(stdin), _O_TEXT)
This is to avoid encoding problems when reading and writing Unicode and UTF-8 encoded XML.
Also this cause unwanted side effects! By using
_setmode(soap->recvfd, _O_BINARY); // found in stdsoap2.cpp
you always assume to read from a file or stdin, however if you set soap->is to a std::istringstream this isn't true.
Just assume you are using getchar() in your main routine, but on a thread you try to deserialize a xml from a std:istringstream (using gsoap xml binding). As result your program will hang. the only way around is to set soap->recvfd = -1;
Regards Ralph
I`m try to realize how to use TinyXML library.
I have to parse this conf file:
<?xml version="1.0" encoding="UTF-8"?>
<Client>
<port num = "20035">
<server_addr ip="127.0.0.1">
<AV_list>
<AV>
<AVNAME>BitDefender</AVNAME>>
<AVPATH> C:\Program Files\Common Files\BitDefender\BitDefender Threat Scanner\av64bit_26308\bdc.exe </AVPATH>
<AVMASK>0x80000000</AVMASK>
<AVCOMMANDLINE> %avpath% \log=%avlog% %scanpath% </AVCOMMANDLINE>
<AVREGEX>(%scanpath%.*?)+(([a-zA-Z0-9]+\\.)+[a-zA-Z]{2,4})+(.+[a-zA-Z_])</AVREGEX>
<AVLOG>C:\log\bd_log.txt</AVLOG>
</AV>
</AV_list>
</Client>
And c++ code
#include "stdafx.h"
#include "iostream"
#include "tinyxml.h"
int main(int argc, char* argv[])
{
TiXmlDocument doc( "D:\\client_conf.xml" );
bool loadOkay = doc.LoadFile();
if ( loadOkay )
printf("Yes \n");
else
printf("No \n");
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlText* pText;
TiXmlHandle hRoot(0);
pElem = hDoc.FirstChildElement().Element();
if (!pElem)
printf("error element");
hRoot = TiXmlHandle(pElem);
pElem = hRoot.FirstChild("server_addr").Element();
const char* info = pElem->Attribute("ip");
printf( "%s \n", info);
pElem = hRoot.FirstChild("port").Element();
info = pElem->Attribute("num");
printf( "%s \n", info);
system("pause");
return 0;
}
Now I can get first two param, but dont figure out how to reach "AV_list" block. Any help will be appreciated. (:
Have a look at the TinyXml Documentation. Your friend is the TiXmlNode Class Reference. You may use most of the Node functions also on TiXmlElements.
You already use the FirstChild() function to get the first child of an element; use the NextSibling() function to iterate over all elements. You can also use the NextSiblingElement() function to get the element directly.
Antother more sophisticated solution would be to use XPath to retrieve elements from the xml file. There is TinyXPath that builds on top of TinyXML. It needs some knowledge of XPath but it might be worth it. (XPath standard)
i am writing a c++ function that will parse .xml file.
i Used system("grep"); type system call to use linux command. now my problem is that i want to select more than one line in given tag. ex.
content of .xml file
====================
<state>
<text> hi this is first li </text>
<sec> dsfn sdlkf sfd </sec>
</state>
===================
i want to print all content between and tag. which and how i can use linux commands.
plz help me....thanks i advance.
Parsing XML using grep is really not a good idea, you should use some c++ xml parsing library like this one:
http://xerces.apache.org/xerces-c/index.html
exec, execve or system calls: demo
#include <stdlib.h>
#include <unistd.h>
int main(int argc, const char* args[])
{
exitcode = system("xsltprox textonly.xslt input.xml > output");
// exitcode = exec("xsltproc", "textonly.xslt", "input.xml");
int exitcode;
}
Proceed to fopen output (or std::fstream reader("output") if you fancy). Note that system is quickly a security hole, so you shouldn't use it in critical apps (like daemons).
Using exec you could redirect. So you could perhaps open a pipe() from your program, fork(), in the child assign the stdout filedescriptor to the pipe() (see dup2 call) and exec in the child.
The parent process can then read the output from the pipe without need for a temp file.
All of this should be on a zillion tutorials, which I don't have to the time to google for you right now.
May I suggest using perl or shell script. If you post an actual example I could show you the code in both shell and c/c++
Update here is how to do it with XSLT
textonly.xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<xsl:for-each select="//*[text()]">
<xsl:if test="text()">
<xsl:value-of select="text()"/>:
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
output demo:
o399hee#OWW00837 ~/stacko
$ xsltproc.exe textonly.xslt input.xml
:
hi this is first li :
dsfn sdlkf sfd :
Use the C functions popen() and pclose()
Here's an example of how to use them:
#include <string>
#include <cstdio>
#include <errno.h>
#include <fstream>
int execShellCommand( const std::string command,
std::string& commandOutput )
{
FILE *fp;
char charBuf;
std::ostringstream stdoutBuffer;
int status;
std::ostringstream errmsg;
// Execute command and save its output to stdout
fp = popen( command.c_str( ), "r" );
if ( fp == NULL ) {
// error handling
} else {
while ( ( charBuf = fgetc( fp ) ) != EOF ) {
stdoutBuffer << charBuf;
}
}
// Wait for completion of command and return its exit status
status = pclose( fp );
if ( status == -1 ) {
// error handling
} else {
commandOutput = stdoutBuffer.str( );
return WEXITSTATUS( status ); // convert exit status
}
}
int main(){
std::string command = "l | grep lib";
std::string commandOutput;
int exitCode = execShellCommand( command, commandOutput);
}