寫了一個很簡陋但可用的XML文件檢視器,一方面是專案剛好有需求,另一方面旨在強迫自己盡快熟悉Silverlight的開發。

這個Silverlight小元件可以嵌在網頁中檢視XML文件,各節點可展開收合,並提供XML原文對照。

Silverlight程式碼如下。其實只是借用Silverlight的TreeView控件,XML原文對照則推給ToolTipService的現成功能:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Xml.Linq;
using System.Windows.Browser;
 
namespace XmlViewer
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            if (HtmlPage.IsEnabled)
                HtmlPage.RegisterScriptableObject("XmlViewer", this);
            //SetXml("Books.xml");
        }
 
        private void setXmlString(string xmlString)
        {
            XDocument xd = XDocument.Parse(xmlString);
            tvXml.Items.Clear();
            tvXml.Items.Add(exploreXElement(xd.Root));
        }
 
        [ScriptableMember]
        public void SetXml(string xml)
        {
            try
            {
                if (xml.StartsWith("<")) setXmlString(xml);
                else
                {
                    WebClient wc = new WebClient();
                    wc.DownloadStringCompleted += (s, e) =>
                    {
                        if (e.Error != null)
                            MessageBox.Show("Invalid XML in " + xml);
                        else
                            setXmlString(e.Result);                        
                    };
                    wc.DownloadStringAsync(new Uri(xml, UriKind.Relative));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Invalid XML content or source!\n" +
                    ex.Message);
                return;
            }
        }
 
        #region TreeView Helper
        SolidColorBrush cPurple = new SolidColorBrush(Colors.Purple);
        SolidColorBrush cBlue = new SolidColorBrush(Colors.Blue);
        SolidColorBrush cGreen = new SolidColorBrush(Colors.Green);
        SolidColorBrush cOrange = new SolidColorBrush(Colors.Orange);
        SolidColorBrush cBlack = new SolidColorBrush(Colors.Black);
 
        //Generate name textblock(fixed width) and value textblock for 
        //XElement or XAttribute
        private Grid genHeader(object obj)
        {
            string n = "", v = "", tp = "";
            SolidColorBrush c = cBlack;
            if (obj is XElement)
            {
                var xe = obj as XElement;
                n = xe.Name.LocalName;
                v = xe.HasElements ? "" : xe.Value;
                //Remove line-break
                v = v.Replace("\r", "").Replace("\n", "");
                while (v.Contains("  "))
                    v = v.Replace("  ", " ");
                tp = xe.ToString();
                c = xe.HasElements ? cBlue : cGreen;
            }
            else if (obj is XAttribute)
            {
                var xa = obj as XAttribute;
                n = "[" + xa.Name.LocalName + "]";
                v = xa.Value;
                tp = "Attribute=" + v;
                c = cPurple;
            }
            Grid g = new Grid();
            g.ColumnDefinitions.Add(new ColumnDefinition() { 
                Width = new GridLength(100) });
            g.ColumnDefinitions.Add(new ColumnDefinition() { 
                Width = GridLength.Auto });
            TextBlock tbName = new TextBlock() { Text = n, Foreground = c };
            if (tp.Length > 0) ToolTipService.SetToolTip(tbName, tp);
            g.Children.Add(tbName);
 
            g.Children.Add(new TextBlock() { Text = v, });
            Grid.SetColumn(g.Children[1] as TextBlock, 1);
            return g;
        }
        //Use recursive to build TreeView nodes
        private TreeViewItem exploreXElement(XElement xe)
        {
            TreeViewItem tvi = new TreeViewItem();
            tvi.Header = genHeader(xe);
            tvi.Tag = xe;
            foreach (var at in xe.Attributes())
                tvi.Items.Add(new TreeViewItem() { 
                    Header = genHeader(at), Tag = at });
            foreach (var ch in xe.Elements())
                tvi.Items.Add(exploreXElement(ch));
            return tvi;
        }
        #endregion
    }
}

在HTML端,可使用Javascript Interop技巧,透過SetXml()傳入XML文件URL或直接傳入XML字串設定要檢視的XML文件:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Silverlight XML Viewer</title>
    <script type="text/javascript" 
            src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.js?WT.mc_id=DOP-MVP-37580" ></script>
    <script type="text/javascript" src="jquery.silverlight4.js"></script>
    <script type="text/javascript">
        $(function () {
            $("#dvXmlViewer").insertSilverlight("XmlViewer.xap", {
                width: 500, height: 480, onLoad: function (s, e) {
                    var slCtrl = s.getHost();
                    window.slXmlViewer = slCtrl.Content.XmlViewer;
                }
            });
            $("#btnLoad").click(function () {
                //Notice: relative to Silverlight XAP folder or absolute uri
                slXmlViewer.SetXml("/SilverlightDemo/XmlViewer/Books.xml");
            });
            $("#btnSet").click(function () {
                slXmlViewer.SetXml(
                '<root><player id="Jeffrey"><score>65535</score></player></root>');
            });
        });
    </script>
</head>
<body>
<input type="button" id="btnLoad" value="Load XML" />
<input type="button" id="btnSet" value="Set XML" />
<div id="dvXmlViewer"></div>
</body>
</html>

備有線上展示供有興趣的朋友測試把玩。


Comments

Be the first to post a comment

Post a comment