Click here to Skip to main content
Click here to Skip to main content

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

, 24 Jul 2001
Rate this:
Please Sign up or sign in to vote.
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.
<!-- Download Links -->

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.

<!-- Article image -->

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, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

About the Author


Comments and Discussions

 
GeneralFailed to create configuration document Pinmemberorcun colak26-Jul-01 3:43 
GeneralRe: Failed to create configuration document PinmemberMark Nischalke26-Jul-01 4:31 
GeneralRe: Failed to create configuration document Pinmemberorcun colak27-Jul-01 5:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 25 Jul 2001
Article Copyright 2001 by Not Active
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid