Solved

Rendering an XML stream

Posted on 2001-06-12
10
753 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

There are two main kinds of selectors in CSS: One is base selector like h1, h2, body, table or any existing HTML tags.  For instance, the following rule sets all paragraphs (<p> elements) to red: (CODE) CSS also allows us to define our own custom …
This article covers the basics of the Sass, which is a CSS extension language. You will learn about variables, mixins, and nesting.
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

734 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