Re: MSXML2.XSLTransform on WM5 exists? Or is there another way?!?

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Hi John:

Thanks :-) (...but i don't know COM from the point of C/C++...which means
I'm always stumblin' around in the dark trying to figure out what's going on
*under* the hood, by looking at the smoke puff patterns coming out of the
tail-pipe...)


Anyway...

I've been thinking a little further on the problem and have come up with the
following idea...(its not great, but its all I've got for now).


a) The first question is how to emulate a parsed Transformer on CE.
Obviously I can't.
But I can hold on to the XslDocument that has done the parsing, which will
cost me in terms of mem used, but save on the speed for subsequent use.
Hence a ProxyTransformer will be needed that wraps around either an
XmlDocument (on CE) or XslTransformer on PC....

b) Then with the code shown yesterday, one can get transformations that will
work on PC and CE.

c) As for injecting argument values into the Xsl ...turns out that if the
XmlDocument holding the Xsl is in mem, it can be manipulated, which means
that param nodes can be injected into the tree.... :-)

With a little bit of work the following should work (untested):

What do you think of this direction? Think it would hold in a pinch /CE:

Sky

//A Proxy XmlDocument to act as a poor man's XmlTransform...
//hold a parsed and treed Xsl document.
public class XSLTInfo {
public string Path { get {return _Path;}}
private string _Path;

#if (CE) || (PocketPC) || (pocketPC) || (WindowsCE)
//CE:
public MSXML2.DOMDocument Document {
get {
if ((_Document == null) && (string.IsNullOrEmpty(_Path)) &&
(File.Exists(_Path))) {
_Document = new MSXML2.DOMDocument();
_Document.load(_Path);
}
return _Document;
}
}
private MSXML2.DOMDocument _Document;
#else
//PC:
// Gets the compiled XSL Template.
public XslCompiledTransform Compiled {
get {
if ((_Compiled == null) && (!string.IsNullOrEmpty(_Path)) &&
(File.Exists(_Path))) {
_Compiled = new XslCompiledTransform();
XsltSettings settings = new XsltSettings();
//MAYBE: settings.EnableScript = true;
_Compiled.Load(_Path, settings, null);
}
return _Compiled;
}
}
private XslCompiledTransform _Compiled;
#endif

public XSLTInfo(string path) {
if (path == null) {throw new System.ArgumentException("path");
if (!File.Exists(path)) {throw new System.ArgumentException("path");
_Path = path;
}
}





static string Transform(XSLTInfo info, string serializedObjectAsXml,
NameValueCollection optionalAttributes) {

#if (CE) || (PocketPC) || (pocketPC) || (WindowsCE)
//A CE way:
//First, the Xsl part...and a manual way of injecting arguments (the only
way? the right way?)
MSXML2.DOMDocument xslDoc = info.Document;
foreach (string entry in optionalAttributes.AllKeys) {
MSXML2.IXMLDOMElement attributeNode =
xslDoc.selectSingleNode(string.Format("//xsl:param[@name='{0}']", entry)) as
MSXML2.IXMLDOMElement;

if (attributeNode == null) {
attributeNode = xslDoc.createElement("xsl:param");
attributeNode.setAttribute("name", entry);
//Insert as first child of xsl:stylesheet node:
//Get first child that is element:
MSXML2.IXMLDOMNode firstChild = xslDoc.documentElement.firstChild;
while ((firstChild != null) && (!(firstChild is MSXML2.IXMLDOMElement))) {
firstChild = firstChild.nextSibling;
}
if (firstChild != null) {
xslDoc.documentElement.insertBefore(attributeNode,
xslDoc.documentElement.firstChild);
}else {
xslDoc.documentElement.appendChild(attributeNode);
}
}
if (attributeNode != null) {
attributeNode.setAttribute("select", string.Format("'{0}'",
optionalAttributes[entry]));
}
}//~keys

//Now deal with the Xml part:
MSXML2.DOMDocument xmlDoc = new MSXML2.DOMDocumentClass();
xmlDoc.loadXML(serializedObjectAsXml);

return xmlDoc.transformNode(xslDoc);
/*
* CANNOT DO THIS ON WM5:
*
// Transform XML data.
string temp = doc.transformNode(xslDoc);
MSXML2.XSLTemplate template = new MSXML2.XSLTemplate();
template.stylesheet = xslDoc;

MSXML2.IXSLProcessor processor;
processor = template.createProcessor();

processor.addParameter("rootDir", rootDir, string.Empty);

processor.input = xmlDoc;
processor.transform();
string result = (string) processor.output;
*/
#else
//A The PC way:
XsltArgumentList argList = new XsltArgumentList();
foreach(string key in optionalAttributes){
argList.AddParam(key, string.Empty, optionalAttributes[key]);
}

//see also: http://www.dotnet247.com/247reference/msgs/17/88816.aspx
StringWriter stringWriter = new StringWriter();
info.Compiled.Transform(xmlReader, argList, stringWriter);
return stringWriter.ToString();

#endif
}



"John Spaith [MS]" wrote:

Sky - first, for someone who claims not to know C++/COM, you get around
pretty well!

Unfortunately XSLTransform stuff isn't supported on CE.
http://msdn2.microsoft.com/en-us/library/aa926556.aspx. Agree it's
misleading that it's still in the header file.

To answer your question in the context of doing what you want to have work
without XSLTransform -- I don't know! Even though I'm the MSXML dev on CE,
most of my work was componentized it for RAM/ROM (obnoxious things like
removing XSLTransform :() and various low level platform stuff, so the
transform stuff I haven't dealt with.

If no one on the newsgroup can help out, actually what I'd do is go to one
of the "real" MSXML discussin groups and explain your problem and the
constraints of the platform. Some folks on newsgroup know this stuff well,
but we're more general system/apps dev folks.

Sorry for issues you're hitting and good luck on getting this fixed.

--
John Spaith
Senior Software Design Engineer
Windows CE Networking
Microsoft Corporation

http://blogs.msdn.com/cenet/.

This posting is provided "AS IS" with no warranties, and confers no rights.
You assume all risk for your use. © 2007 Microsoft Corporation. All rights
reserved.

"Sky" <public.skysigal{*AT*}xact-solutions.com> wrote in message
news:C554C53C-A9CB-4A09-A9E1-CDB4F17E02EF@xxxxxxxxxxxxxxxx
Hello:

I've been looking all over the place for a way to transform XML via XSL on
a
PocketPC, using Params.
And although have had some success (described below), still am missing one
or two crucial parts...namely, parameters.

Any help would be greatly appreciated!

Setup:
I found a brief hint on the net that indicated that NET 2.0 CF did not
have
XSL methods built in, but that they could be done via ActiveX as follows:

a) install C++ tools from VS2005
b) in order to have MIDL.EXE installed,
c) then run it as follows:
C:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC
SDK\Include\Armv4i>midl msxml2.idl /I "C:\Program Files\Microsoft Visual
Studio 8\VC\PlatformSDK\Include"

to get a MSXML20.tlb
d) which i then included in a C# program.

That done, I tried the following, which works:


The following then works to transform the XML with XSL:

string TransformNoArgs(string xmlFilePath, string xslFilePath){
MSXML2.DOMDocument xml = new MSXML2.DOMDocumentClass();
xml.load(xmlFilePath);

MSXML2.DOMDocument xsl = new MSXML2.DOMDocumentClass();
xsl.load(xslFilePath);

// Transform XML data.
return xml.transformNode(xsl);
}

This works fine. Its not cached, so it is a heavy solution...but it works
as
promised.


The remaining, but crucial, problem is to find a way to inject arguments
into an xsl that is used on PC and PPC, that includes params such as the
following:

<xsl:param name="cssDirPath"/>
<xsl:param name="imgDirPath"/>
<xsl:param name="dataSourceName"/>



I then tried the following method:

string TransformWithArgs(string xmlFilePath, string xslFilePath){
MSXML2.DOMDocument xml = new MSXML2.DOMDocumentClass();
xml.load(xmlFilePath);

MSXML2.DOMDocument xsl = new MSXML2.DOMDocumentClass();
xsl.load(xslFilePath);

MSXML2.XSLTemplate template = new MSXML2.XSLTemplate();
template.stylesheet = xsl;

MSXML2.IXSLProcessor processor;
processor = template.createProcessor();

processor.addParameter("rootDir", C_ROOT_DIR, string.Empty);
processor.addParameter("cssDirPath", C_CSS_DIR, string.Empty);
processor.addParameter("imgDirPath", C_IMG_DIR, string.Empty);

processor.input = xml;
processor.transform();
return (string)processor.output;
}


But it fails on XSLTemplate saying it cannot create XSLTemplate.
I am assuming that this is because there is a stub there in the *.h file,
but the code was not ported to CE (I'm probably wrong -- I know almost
nothing about C, C++, and COM really)

So my question is simply
a) Is there a way to inject Param values without using XSLTransform so
that
the XSLT can be used as is...
b) What other way could I create a parametricizeable transformations, in a
format that will work both on CE and PC (it would be a nightmare to have
to
rewrite a lot of files that I already have, and would prefer to find a
code
solution/change rather than a XSL change if it can be done...)


Many many thanks!
Sky





.



Relevant Pages