Solved

Rendering an XML stream

Posted on 2001-06-12
10
739 Views
Last Modified: 2013-11-20
With XML/XSL adding such great capabilities for formatting output I would like to be able to stream XML data into a CHTMLView.  While the XSL sheet can reside in the program directory, the XML is produced dynamically as output from various calculations with the view rendering it in the same way that it does if you load an xml document from the local drive.  Is it possible to insert items into an XML document and have it render (using the XSL sheet) as each element is added as with HTML? Can anyone show me a way of going about this?

Regards

David
0
Comment
Question by:Rupreck
  • 6
  • 3
10 Comments
 
LVL 49

Accepted Solution

by:
DanRollins earned 300 total points
ID: 6184075
First, let's not forget the obvious:  You can simply dump the XML to a temporary file on the hard disk, then display it.  That is the cleanest and simplest solution and the one least likely to cause problems.  If you want to do it that way, and don't know how, just ask.

That said, if you really need to avoid the temporary-file, then try loading XML text from memory using the same techniques that can be used to feed HTML into an CHtmlView.  To wit:

Here's the easiest way:
#include <mshtml.h>
#include <atlbase.h>

CString gsHtmlPage="This is some body text <b>from memory</b>!";

void CSdiHtmlView::OnDocumentComplete(LPCTSTR lpszURL)
{
    CHtmlView::OnDocumentComplete(lpszURL);

   HRESULT hr;
   IHTMLDocument2*  spDoc= (IHTMLDocument2*)GetHtmlDocument();
   IHTMLElement*    pElem= NULL;

   hr= spDoc->get_body( &pElem ); // prolly ought to do some error checking
   CComBSTR bstrHtml= gsHtmlPage;
   hr= pElem->put_innerHTML( bstrHtml );  // set the body text
}
=-=-=-=-=-=-=-=-=-
First navigate to some page (eg, about:blank) then the above code kicks in.  

=-=-=-=-=-=-=-=-=-
Here's another way:

To display a very short page, you can use the
about:
protocol.  For instance:

Navigate("about:"<html><body>This page was loaded from <b>memory!</b></body></html>", 0,0,0 );

=-=-=-=-=-=-=-=-=-
There is another way that is more complicated, involving creating a stream from a memory block:

// include <HTML><BODY> with this technique
CString gsHtmlPage="<HTML><BODY>This is some body text <b>from memory</b>!</body></html>";

void CSdiHtmlView::OnDocumentComplete(LPCTSTR lpszURL)
{
   static BOOL fDoneOnce= FALSE; // reentrancy kludge
   if ( fDoneOnce ) {
       fDoneOnce= FALSE;
       return;
   }
   fDoneOnce= TRUE;

   IPersistStreamInit* pPersistStreamInit= NULL;

   DWORD nPgLen= gsHtmlPage.GetLength();
   HRESULT hr;
   HGLOBAL hMemPage=  GlobalAlloc( GPTR, nPgLen+1 );
   LPSTR   pMemPage=  (LPSTR)GlobalLock( hMemPage );
   memcpy( pMemPage, (LPCSTR)gsHtmlPage, nPgLen+1 );
   GlobalUnlock( hMemPage );

   LPSTREAM pStm;
   hr= CreateStreamOnHGlobal( hMemPage, TRUE, &pStm );
   if( SUCCEEDED(hr) ) {
       LPDISPATCH pHtmlDoc= GetHtmlDocument();
       if ( pHtmlDoc ) {
           hr= pHtmlDoc->QueryInterface( IID_IPersistStreamInit, (void**)&pPersistStreamInit );
           hr= pPersistStreamInit->InitNew();  // Initialize it with the storage we created
           hr= pPersistStreamInit->Load( pStm );
       }
   }
   if( pPersistStreamInit ) {
       pPersistStreamInit->Release();
   }
   GlobalFree( hMemPage );
}

-- Dan
0
 

Author Comment

by:Rupreck
ID: 6186715
Hi Dan,
Thanks very much for your suggestions however I have some bad news to report.  All these methods work well with HTML however not with XML.

1) Method 1
I already knew the first method and unfortunately it seems to not be able to trigger the XML engine in IE to kick in or something and this may be part of the .innerHTML() command.  After loading about:blank and then this XML string:

gsHtmlPage =  "<?xml version=\"1.0\" standalone=\"no\"?>\r\n";
gsHtmlPage += "<xml-stylesheet type=\"text/xsl\" href=\"olssamp.xsl\">\r\n";
gsHtmlPage += "<!-- Here begins the XML data -->\r\n";
gsHtmlPage += "<OUTPUT>\r\n";
gsHtmlPage += "<METHOD ID=\"OLS\">\r\n";
gsHtmlPage += "<COMMAND>OLS CONSUME INCOME PRICE / ANOVA PCOV</COMMAND>\r\n";
gsHtmlPage += "</METHOD>\r\n";
gsHtmlPage += "</OUTPUT>";


the resultant output on the screen is a plain black:

OLS CONSUME INCOME PRICE / ANOVA PCOV

i.e. the default behaviour for unrecognised HTML tags has them ignored and the remainder of the text simply outputted.  However when making that block into a file and double clicking it to load in IE the associated style sheet (correctly) turns this command blue.  Style sheet is placed in all the appropriate directories.

2) Method 2
This method automatically inserts the tags <HTML> </HTML> around the text fooling the XML engine.  This time the text does not appear.  Removing the 'about:' makes the problem worse.

3) Method 3
Again a blank page.  Right clicking to 'View Source' shows the correct xml data loaded but nothing displayed.  Replacing the href with an internet link (href=\"http://207.5.45.208/other/shazam/olssamp.xsl\")
I can see via modem activity that this file was never accessed.

So I am stumped.   If you have any other suggestions I would be most grateful.  You are right in suggesting that the temp file method is inappropriate.  The need to have this load (appearing to scroll) as output comes through is important in keeping with the style of the current program.
Scrolling is simple however I am hoping that the xml will render as it is loaded (like a lengthy simple HTML page) with the right options.

Regards

David
0
 

Author Comment

by:Rupreck
ID: 6192275
To add to this.  It seems that I can get some xml to display using:

// Load the default xml document
CString sAppName=AfxGetAppName();
CString sResourceID;
sResourceID.Format("%d", IDR_EMPTY_XML);
CString sNavigatePath;
sNavigatePath ="res://"+sAppName+".exe/"+sResourceID;
Navigate2(sNavigatePath);

Where the resource in this case is inserted as an HTML page containing XML.  ie

<?xml version="1.0" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="file://c:\OLSSAMP.xsl"?>
<!-- Here begins the XML data -->
<OUTPUT>
  <METHOD ID="OLS">
    <COMMAND>OLS CONSUME INCOME PRICE / ANOVA PCOV</COMMAND>
  </METHOD>  
</OUTPUT>

I can now add text to the window using Dans method 3) above however it is treated as html again and the tags are ignored.

I have a feeling that having xml stream into IE and expecting it to render with the xsl sheet dynamically is impossible.  Microsoft probably haven't seen a need for this although HTML is rendered correctly with the right formatting.

David
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 

Author Comment

by:Rupreck
ID: 6192676
To add to this.  It seems that I can get some xml to display using:

// Load the default xml document
CString sAppName=AfxGetAppName();
CString sResourceID;
sResourceID.Format("%d", IDR_EMPTY_XML);
CString sNavigatePath;
sNavigatePath ="res://"+sAppName+".exe/"+sResourceID;
Navigate2(sNavigatePath);

Where the resource in this case is inserted as an HTML page containing XML.  ie

<?xml version="1.0" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="file://c:\OLSSAMP.xsl"?>
<!-- Here begins the XML data -->
<OUTPUT>
  <METHOD ID="OLS">
    <COMMAND>OLS CONSUME INCOME PRICE / ANOVA PCOV</COMMAND>
  </METHOD>  
</OUTPUT>

I can now add text to the window using Dans method 3) above however it is treated as html again and the tags are ignored.

I have a feeling that having xml stream into IE and expecting it to render with the xsl sheet dynamically is impossible.  Microsoft probably haven't seen a need for this although HTML is rendered correctly with the right formatting.

David
0
 

Author Comment

by:Rupreck
ID: 6222591
No solution has been found to this.  Dans suggestion applied well to HTML however not to XML so that no answer to how to render an XML stream has been found.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6307221
The key seems to be gettign the IDispatch* for the XMLDOMDocument.  Are you interested in followup?

-- Dan
0
 

Author Comment

by:Rupreck
ID: 6321699
Actually I posted the question again as 'Rendering an XML Stream II' and the accepted answer was given as:

1) create 2 IXMLDOMDocument objects
2) set the async property on both to false
3) load 1 with the xml and the other with the xsl documents
4) BSTR bstrHTML=xmlDoc.transformNode(xslDoc);
5) insert the html into your browser (which you seem to know how to do)

I then did it in c++ and will post the code somewhere in time.

Thanks for the comment

David
0
 
LVL 27

Expert Comment

by:Asta Cu
ID: 6907039
Please update the expert here who have so willingly stepped in to help you, since much time has passed since your last comments, and Email notifications may not have been generated to the participating experts here due to some problems at that time.  If you've been helped, accept the respective question by that expert to grade and close it.

Somewhat off-topic, but important.

****************************** ALERT********************************
WindowsUpdate - Critical Update alert March 28, 2002 from Microsoft
http://www.microsoft.com/technet/treeview/default.asp?url=/technet/security/bulletin/ms02-015.asp
Synopsis:
Microsoft Security Bulletin MS02-015  
28 March 2002 Cumulative Patch for Internet Explorer
Originally posted: March 28, 2002
Summary
Who should read this bulletin: Customers using Microsoft® Internet Explorer
Impact of vulnerability: Two vulnerabilities, the most serious of which would allow script to run in the Local Computer Zone.
Maximum Severity Rating: Critical
Recommendation: Consumers using the affected version of IE should install the patch immediately.
Affected Software:
Microsoft Internet Explorer 5.01
Microsoft Internet Explorer 5.5
Microsoft Internet Explorer 6.0

Thought you'd appreciate knowing this.
":0)
Asta
0
 

Author Comment

by:Rupreck
ID: 7137102
The answer for XML is in my later comments however these methods are the best way to get HTML into the browser; which is needed after the .TransformNode() method.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7137196
Thanks Rupreck.  This is good information.  I appreciate your returning to finalize this Q.  -- Dan
0

Featured Post

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
Styling your websites can become very complex. Here I'll show how SASS can help you better organize, maintain and reuse your CSS code.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
The viewer will learn the benefit of using external CSS files and the relationship between class and ID selectors. Create your external css file by saving it as style.css then set up your style tags: (CODE) Reference the nav tag and set your prop…

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question