Vikur
asked on
TransformNode() MSXML using C++ doesn't work
Hi,
A following code retutn exeption on loadXML function. What is wrong ?
#include <windows.h>
#import <msxml3.dll>
typedef MSXML2::IXMLDOMDocumentPtr DocPtr;
typedef MSXML2::IXMLDOMNodePtr NodePtr;
void get_error(DocPtr doc)
{
MSXML2::IXMLDOMParseErrorP tr pErr = doc->GetparseError();//par seError;
if( pErr->GeterrorCode() != 0)
throw pErr->Getreason();
else
AfxMessageBox ("loaded successfuly");
}
////////////////////////// ////////// ///
void tform(char* c_args)
{
CoInitialize(NULL);
try
{
DocPtr xmlDoc(__uuidof(MSXML2::DO MDocument) );
//This loads the text that I want to transform
xmlDoc->load(c_args);
get_error(xmlDoc);
//This loads the XSLT transform
DocPtr xslDoc(__uuidof(MSXML2::DO MDocument) );
xslDoc->load("sam1.xsl");
get_error(xmlDoc);
//This transforms
DocPtr xmlDso(__uuidof(MSXML2::DO MDocument) );
NodePtr xmlroot = xmlDoc->GetdocumentElement ();
NodePtr xslroot = xslDoc->GetdocumentElement ();
_bstr_t str = xmlroot->transformNode(xsl root) ;
// THERE IS FAULT OCCURE
xmlDso->loadXML(str);
get_error(xmlDso);
xmlDso->save("newFile.xml" );
}
catch(char* lpstrErr) {
// Some error...
AfxMessageBox(lpstrErr );
} catch(...) {
// Unknown error...
AfxMessageBox("Unknown error..." );
}
CoUninitialize();
}
////////////////////////// ////////// /
<?xml version="1.0" encoding="UTF-8"?>
<source>
<title>XSL</title>
<author>John Smith</author>
</source>
////////////////////////// ////////// /////////
<xsl:stylesheet version = '1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:template match="/">
<h1>
<xsl:value-of select="//title"/>
</h1>
<h2>
<xsl:value-of select="//author"/>
</h2>
</xsl:template>
</xsl:stylesheet>
A following code retutn exeption on loadXML function. What is wrong ?
#include <windows.h>
#import <msxml3.dll>
typedef MSXML2::IXMLDOMDocumentPtr
typedef MSXML2::IXMLDOMNodePtr NodePtr;
void get_error(DocPtr doc)
{
MSXML2::IXMLDOMParseErrorP
if( pErr->GeterrorCode() != 0)
throw pErr->Getreason();
else
AfxMessageBox ("loaded successfuly");
}
//////////////////////////
void tform(char* c_args)
{
CoInitialize(NULL);
try
{
DocPtr xmlDoc(__uuidof(MSXML2::DO
//This loads the text that I want to transform
xmlDoc->load(c_args);
get_error(xmlDoc);
//This loads the XSLT transform
DocPtr xslDoc(__uuidof(MSXML2::DO
xslDoc->load("sam1.xsl");
get_error(xmlDoc);
//This transforms
DocPtr xmlDso(__uuidof(MSXML2::DO
NodePtr xmlroot = xmlDoc->GetdocumentElement
NodePtr xslroot = xslDoc->GetdocumentElement
_bstr_t str = xmlroot->transformNode(xsl
// THERE IS FAULT OCCURE
xmlDso->loadXML(str);
get_error(xmlDso);
xmlDso->save("newFile.xml"
}
catch(char* lpstrErr) {
// Some error...
AfxMessageBox(lpstrErr );
} catch(...) {
// Unknown error...
AfxMessageBox("Unknown error..." );
}
CoUninitialize();
}
//////////////////////////
<?xml version="1.0" encoding="UTF-8"?>
<source>
<title>XSL</title>
<author>John Smith</author>
</source>
//////////////////////////
<xsl:stylesheet version = '1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:template match="/">
<h1>
<xsl:value-of select="//title"/>
</h1>
<h2>
<xsl:value-of select="//author"/>
</h2>
</xsl:template>
</xsl:stylesheet>
I would suspect that "bstr_t str = xmlroot->transformNode(xsl root);" has not produced a well-formed XML string. Try adding a box to output it before loading. Futhermore what did the ParseError object return for reason code and column position?
ASKER
You absolutely right: transformNode return a following string
""<?xml version="1.0" encoding="UTF-8"?XSLJohnSm
So , it erases all tag names from XML and nothing else - without any error. Why ? may be somthing wrong on XSLT ?
Now that is a VERY strange string"! The back > is missing.
You do have another error. After creating the DOM objects you MUST set the property async to false, otherwise the object creates a thread and executes the loading in background. Your thread is still running and the other threads have not yet started so there is no error object and consequently the transform could go wrong. Put that in first.
You do have another error. After creating the DOM objects you MUST set the property async to false, otherwise the object creates a thread and executes the loading in background. Your thread is still running and the other threads have not yet started so there is no error object and consequently the transform could go wrong. Put that in first.
ASKER
Sorry,my error
returned a following string :
"<?xml version="1.0" encoding="UTF-16"?> XSL John Smith(1)"
What are you think
why
encoding="UTF-16" instead of encoding="UTF-8" ?
returned a following string :
"<?xml version="1.0" encoding="UTF-16"?> XSL John Smith(1)"
What are you think
why
encoding="UTF-16" instead of encoding="UTF-8" ?
"What are you think"
The encoding is correct, since you have a BSTR which is a w_char type ie: 16 bit characters. The official type for this is actually UTF-16.
You MUST set the async property to false!!!!!
The encoding is correct, since you have a BSTR which is a w_char type ie: 16 bit characters. The official type for this is actually UTF-16.
You MUST set the async property to false!!!!!
ASKER
Thanks and sorry for mistake. Anyway ...
I have corrected it and it doesn't help ( puting async to false). Seems, somthing wrong with encoding :
Input first string : <?xml version="1.0" encoding="UTF-8"?>
Output ( as mentioned ) : "<?xml version="1.0" encoding="UTF-16"?> XSL John Smith(1)"
So , first of all, it change encoding ( When I change it to UTF-16 it fails on xmlDoc->load . I check it now )
On the other hand it transforms body wrongly : I expect to recieve on output somthing like
.............
<h1>
XSL
</h1>
<h2>
John Smith
</h2>
and not
XSL John Smith(1)
Or it shoud be so - without tag names ?
Thanks
I have corrected it and it doesn't help ( puting async to false). Seems, somthing wrong with encoding :
Input first string : <?xml version="1.0" encoding="UTF-8"?>
Output ( as mentioned ) : "<?xml version="1.0" encoding="UTF-16"?> XSL John Smith(1)"
So , first of all, it change encoding ( When I change it to UTF-16 it fails on xmlDoc->load . I check it now )
On the other hand it transforms body wrongly : I expect to recieve on output somthing like
.............
<h1>
XSL
</h1>
<h2>
John Smith
</h2>
and not
XSL John Smith(1)
Or it shoud be so - without tag names ?
Thanks
First of all the UTF-16 encoding is correct. Don't change anything.
Second the transform function has included a correct XML header but has not output any XML text - just RAW text. Can you post your transform XSL here? I suspect that the <xsl:output method="...."/> is incorrect. The DEFAULT is actually HTML but if it is incorrectly specified the transformer "guesses" and it looks as if it has guessed "text" but added a header.
Second the transform function has included a correct XML header but has not output any XML text - just RAW text. Can you post your transform XSL here? I suspect that the <xsl:output method="...."/> is incorrect. The DEFAULT is actually HTML but if it is incorrectly specified the transformer "guesses" and it looks as if it has guessed "text" but added a header.
ASKER
My XSL
After correction ( added <xsl:output method="HTML"/> ) :
<xsl:stylesheet version = '1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method="HTML"/>
<xsl:template match="/">
<h1>
<xsl:value-of select="//title"/>
</h1>
<h2>
<xsl:value-of select="//author"/>
</h2>
</xsl:template>
</xsl:stylesheet>
And now my output : "XSLJohn Smith" - without header line .
I goiwng to try to use TransformNodeToObject instead ,as recommended on MSDN.
Thanks a lot
After correction ( added <xsl:output method="HTML"/> ) :
<xsl:stylesheet version = '1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method="HTML"/>
<xsl:template match="/">
<h1>
<xsl:value-of select="//title"/>
</h1>
<h2>
<xsl:value-of select="//author"/>
</h2>
</xsl:template>
</xsl:stylesheet>
And now my output : "XSLJohn Smith" - without header line .
I goiwng to try to use TransformNodeToObject instead ,as recommended on MSDN.
Thanks a lot
So you had no <xsl:output/> tag?
In which case to get XML output the tag should read :-
<xsl:output method="xml" omit-xml-declaration="no" standalone="yes"/>
which will give you :-
<?xml version="1.0" standalone="yes" encoding="utf-16"?>
<h1>title</h1><h2>author</ h2>
better would be :-
<xsl:template match="/">
<h>
<h1>
<xsl:value-of select="//title"/>
</h1>
<h2>
<xsl:value-of select="//author"/>
</h2>
</h>
</xsl:template>
which gives you a single root node, you can then repeat the other tags inside it.
HTH
In which case to get XML output the tag should read :-
<xsl:output method="xml" omit-xml-declaration="no" standalone="yes"/>
which will give you :-
<?xml version="1.0" standalone="yes" encoding="utf-16"?>
<h1>title</h1><h2>author</
better would be :-
<xsl:template match="/">
<h>
<h1>
<xsl:value-of select="//title"/>
</h1>
<h2>
<xsl:value-of select="//author"/>
</h2>
</h>
</xsl:template>
which gives you a single root node, you can then repeat the other tags inside it.
HTH
ASKER
Thank you - it's really works.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.