WPF XML Browser Control


Ever wondered how to get a IE like look and feel of the xml in the default WPF web browser control? If your answer is – “Just navigate the Web Browser to the xml path”; You are right! But if you have to navigate to a in-memory xml? Read on to know and apply IE like styling for xml stored in a string variable.

Idea of writing a custom based xml browser control came in because I had a requirement to edit the xml on fly and validate it against a specified schema. User is allowed to edit only the standard xml(compiled as an embedded resource) that the tool provides and not navigate to any path.

This control helps you:

  1. Load the xml from the string and apply IE like styling
  2. Edit the xml
  3. Validate the xml against the defined schema

Before I go further, here is what you get:

image

The problem with web browser when navigating to a string is that it does not load the style for it. Hence the work around is to transform the xml and navigate to it. To do so you need the Xslt that IE uses. After googling for “xml pretty print”, I finally got one originally written by Jonathan Marsh of Microsoft for IE5 and modified by Steve Muench for conversion to XSLT 1.0 REC.  Copy the xml from here.

And here is the code to transform it:

/// <summary>
        /// Executes when XmlDoc DP is changed, Loads the xml and tranforms it using XSL provided
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        public static void OnXmlDocChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var browserControl = d as XmlBrowserControl;
            if (browserControl == null) return;
            var xmlString = e.NewValue as string;
            
            try
            {

                var xmlDocument = new XmlDocument();

                var xmlDocStyled = new StringBuilder(2500);
                // mark of web – to enable IE to force webpages to run in the security zone of the location the page was saved from
                // http://msdn.microsoft.com/en-us/library/ms537628(v=vs.85).aspx
                xmlDocStyled.Append("<!– saved from url=(0014)about:internet –>");

                var xslt = new XslCompiledTransform();
                //TODO: Do not forget to change the namespace, if you move the xsl sheet to your application
                var xsltFileStream =
                    typeof(XmlBrowserControl).Assembly.GetManifestResourceStream(
                        "WPFXmlBrowser.Controls.XmlBrowser.Resources.xml-pretty-print.xsl");
                if (xsltFileStream != null)
                {
                    //Load the xsltFile
                    var xmlReader = XmlReader.Create(xsltFileStream);
                    xslt.Load(xmlReader);
                    var settings = new XmlWriterSettings();
                    // writer for transformation
                    var writer = XmlWriter.Create(xmlDocStyled, settings);
                    if (xmlString != null) xmlDocument.LoadXml(xmlString);
                    xslt.Transform(xmlDocument, writer);

                }

                browserControl.EditText.Text = xmlString;
                browserControl.WebBrowser.NavigateToString(xmlDocStyled.ToString());
                browserControl.EditButton.Visibility = System.Windows.Visibility.Visible;
                browserControl.CopyClipButton.Visibility = System.Windows.Visibility.Visible;
            }
            catch (Exception ex)
            {
                browserControl.WebBrowser.NavigateToString("Unable to parse xml. Correct the following errors: " + ex.Message);
            }
        }

 

XSLT is provided as an embedded resource and it is loaded from the code. If you are moving the xslt to your project, make sure to change the namespace in the calling code.

image

You can download the code from my share here. This code works on my machine!

Feel free to modify the code, but as usual you don’t get warranty!

/*Nish*/

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s