Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Using XML, XSL, DHTML and Javascript in your Windows applications

0.00/5 (No votes)
24 Jul 2001 1  
This article shows how to dynamically create XML documents, transform these using XSL and then displays the resulting HTML into a browser control. Also demonstrates using HTML and images from resources.

Summary

This application uses WTL, COM, XML, HTML, DHTML and JavaScript. It will demonstrate creating a custom command bar that includes two combo boxes and the creation of XML documents. It will also demonstrate dynamically inserting new elements into the XML document, transforming it using XSL, and dynamically inserting the resulting HTML into a HTML page. It will also show how to use a HTML and images from resources.

Sample Image - XML_HTML.gif

Overview

Once upon a time I had a project for a client that involved converting text files containing summaries of news articles, culled from various sources around the world, into XML documents. The XML would then be entered into a database. After this phase was complete I put together a prototype of an editor to create the XML documents directly without the intermediary text files. For various reasons the client was never heard from again.

During the development of this prototype I ran into several problems that I could find no previous examples of so I thought other developers may find my solutions of value.

Details

The application is written using WTL to keep it a small as possible and reduce the number redistributable files. It uses an XML based configuration document to control the contents of some combo boxes. This allows easy extensibility by the end user.

A splitter frame is used to display a form view in the left pane and a HTML view in the right pane. On start up the right pane is full screen.

m_Splitter.SetSinglePaneMode(SPLIT_PANE_RIGHT);

To start a new document select File->New. A dialog will be displayed asking for the volume and issue. This is used to name the file and is embedded in the XML document as an attribute of the root element. After clicking OK a new document is created using MSXML which contains the basic elements necessary. The test1_1.xml file in the samples shows this basic file.

You will notice the customized command bar that includes two combo boxes. This are filled in a startup by reading the config.xml file. The contents are also used to create the new XML document framework.

After clicking OK on the New Document dialog the left pane is displayed full screen. The user can then enter the information necessary and select keywords that apply to the article and select the date. When complete they click on the Enter button.

After the Enter button is clicked the data is recovered from the fields using DDX and entered into the previously created XML document template. To place the article in the document correctly a XPATH search is formatted from the current combo box selections and the node is selected. The data is then appended to this node.

CString strSearch;
strSearch.Format(_T("/*/*[@name=\"%s\"]"), m_ComboBar.GetSection());
if( FAILED(m_pNewDoc->selectSingleNode(A2OLE(strSearch), &pSection) ) )
    return FALSE;

After this step, the newly created node is transformed by XSL and sent to the HTML view. To reduce the number of support files and because the XSL was small I included it a string resource.

CString strXSL;
strXSL.LoadString(IDS_XSL);

short bSuccess;
if( FAILED(m_pXSLDoc->loadXML(A2OLE(strXSL),&bSuccess) ) )
    return FALSE;
    
CComBSTR bstrOutput;
if( SUCCEEDED(pArticle->transformNode(m_pXSLDoc,&bstrOutput) ) )
    m_HTMLView.InsertElement(OLE2A(bstrOutput));

Once the transformed XML is sent to the HTML view it is inserted into the current document. This is accomplished by getting the IWebBrowser2 interface from the HTML control, finding the body element of the document and inserting the HTML before the end of the last element. Again to reduce support files, the HTML page is stored as a resource. Expanding or collapsing the article is accomplished by JavaScript connected to the image next to the title.

BOOL CXMLView::GetBody()
{
    // Get the browser interface from the embedded HTML control

    CComPtr<IWEBBROWSER2> spBrowser;
    if( SUCCEEDED(QueryControl(__uuidof(spBrowser), reinterpret_cast<void**>(&spBrowser))) )
    {
        // Get the document element

        CComPtr<IDISPATCH> pDisp;
        if( SUCCEEDED(spBrowser->get_Document(&pDisp)) && pDisp)
            { // Get the body

            element if( SUCCEEDED(pDisp.QueryInterface(&m_pDoc)) && m_pDoc
            )
                { if(SUCCEEDED(m_pDoc->get_body(&m_pBody)) && m_pBody )
                    return TRUE;        
            }
        }
    }
    return FALSE;
}

void CXMLView::InsertElement(CString strElement)
{
    USES_CONVERSION;
    
    // If the body has not been stored yet then attempt to find it

    if( !m_pBody )
    {
        if( !GetBody() )
        {
            MessageBox(_T("Body not found.\n\nPlease close application"), _T("Critical Error"), MB_ICONERROR);
            return;
        }
    }
    
    // Get the elements on this page

    CComPtr<IDISPATCH> pDisp;
    if( SUCCEEDED(m_pBody->get_all(&pDisp)) && pDisp)
    {
        // Get the ElementCollection

        CComQIPtr<IHTMLELEMENTCOLLECTION> 
        pColl(pDisp);
        if(pColl)
        {  
            // Make sure there are items in the collection 

            long lCount; 
            if(SUCCEEDED(pColl->get_length(&lCount)) && lCount  > 0)
            { 
                // Show/Hide the element

                ToggleElement(pColl); 
                
                // Release the dispatch to be reused and get the 

                // the last item in the    collection

                pDisp.Release(); 
                CComVariant varName,varIndex(lCount);
                pColl->item(varName, varIndex, &pDisp);

                // Get the element returned above and insert the text

                // before the end of it

                CComQIPtr<IHTMLELEMENT> pElement(pDisp);
                if(pElement)
                    pElement->insertAdjacentHTML(A2OLE("beforeEnd"), A2OLE(strElement));
            }
        }
    }
}

Once the document has been completed it can be saved by selecting File->Save. This will bring up a Folder selection dialog.

Improvements

There is always room for improvement. Since this was created as a prototype I left several thing unfinished. In the future I may enhance this to allow editing of previously created documents.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here