65.9K
CodeProject 正在变化。 阅读更多。
Home

Firefox 书签管理器(使用 C# 和 XML)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.47/5 (27投票s)

2008 年 7 月 28 日

CPOL

3分钟阅读

viewsIcon

129199

downloadIcon

3082

使用 KingMark,您可以交换 Firefox 和 IE 之间的书签。

Firefox bookmark manager

Firefox bookmark manager

引言

这是一个简单的 Firefox 书签管理器。使用 KingMark,您可以将 Firefox 书签导入、管理并导出为 HTML 或 *.url 或 XML 文件。KingMark 使用 XML,首先将 Firefox 书签文件转换为 XML 文件,然后将其转换为 HTML 文件。

Using the Code

创建 XML 文件

KingMark 为每个节点创建具有唯一名称的 XML 文件。例如,这是 XML 文件中的一个节点

<NODE9 NAME="FireFox" ADD_DATE="1213909970" 
		LAST_MODIFIED="1220234375" DESC="">
    <BOOKMARK10 NAME="Mozilla - Home" 
		HREF="http://en-us.www.mozilla.com/en-US/" 
		  SHORTCUTURL="mozila" DESC="" 
        ADD_DATE="1183006386" LAST_MODIFIED="1220234476" 
        ICON_URI="" ICON="" />

    <BOOKMARK11 NAME="mozillaZine Forums" 
		HREF="http://forums.mozillazine.org/index.php" 
        SHORTCUTURL="" DESC="" ADD_DATE="1214351419" LAST_MODIFIED="1220233809" 
        ICON_URI="" ICON="" />

    <BOOKMARK12 NAME="Mozilla Support" 
		HREF="http://support.mozilla.com/tiki-my_tiki.php#content_forum" 
        SHORTCUTURL="" DESC="" ADD_DATE="1214143305" LAST_MODIFIED="1220233808" 
        ICON_URI="" ICON="" />

    <BOOKMARK13 NAME="AfzoneHaye FF" 
		HREF="http://addons.mozillafirefox.ir/" SHORTCUTURL="" 
        DESC="" ADD_DATE="1218070432" LAST_MODIFIED="1219953174" 
        ICON_URI="" ICON="" />

</NODE9>

正如您所看到的,每个节点都有一个唯一的名称,所以我使用这些名称来命名 TreeView 节点名称。通过这种命名方式,我们可以轻松地在 XML 文件和 TreeView 控件中找到每个节点。

我将最大的节点号(例如:<BOOKMARK13 ... />)保存在根节点的属性 (ELEMENTS) 中。通过此属性,我们可以找到命名中使用的最新数字,并在此之后开始命名。通过 OPTIMIZE XML FILE,KingMark 会排列 XML 元素。

首先:KingMark 将 FF BookMark 文件(HTML 文件)转换为 List<string> 对象(中间代码)

您可以通过在“设置”中检查跟踪来查看中间代码。

当您选中“跟踪”时,private void trace(List<string> list) 方法会在您的 FF 书签文件旁边创建一个 trace.txt 文件,其中包含用于生成 XML 文件的中间代码。

在 KingMark 将 List<string> 对象转换为 XML 文件后,使用 System.Xml.XmlWriter 类和以下方法

private void ListToXml(List<string> list)
{
    string name = "";
    string href = "";
    string icon = "";
    string iconUrl = "";
    string desc = "";
    string keyWords = "";
    string addDate = "";
    string lastModified = "";
    try
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        //settings.NewLineOnAttributes = true;
        settings.Encoding = Encoding.UTF8;
        settings.ConformanceLevel = ConformanceLevel.Document;
        System.Xml.XmlWriter Writer;
        Writer = XmlWriter.Create(temporaryFileName, settings);
        Writer.WriteStartDocument();
        Writer.WriteComment(XmlDescription);
        Writer.WriteStartElement(rootNodeName);
        Writer.WriteAttributeString("ELEMENTS", list.Count.ToString());
        for (int i = 1; i < list.Count; i++)
        {
            //Nodes separator
            if (Regex.IsMatch(list[i], @"\<HR\>"))
            {
                //Writer.WriteStartElement("HR");
                //Writer.WriteEndElement();
                continue;
            }
            else if (Regex.IsMatch(list[i], @"\<NODE\>"))
            {
                //node's NAME
                name = Regex.Match(list[i - 1].Trim(), "NAME=\"[^\"]*\"").ToString();
                name = Regex.Replace(name, "NAME|\"|=", "");
                //node's DESC
                desc = Regex.Match(list[i - 1].Trim(), 
					"DESC=\"[^\"]*\"").ToString();
                desc = Regex.Replace(desc, "DESC|\"|=", "");
                //node's ADD_DATE
                addDate = Regex.Match(list[i - 1].Trim(), 
					"ADD_DATE=\"[^\"]*\"").ToString();
                addDate = Regex.Replace(addDate, "ADD_DATE|\"|=", "");
                //node's LAST_MODIFIED
                lastModified = Regex.Match(list[i - 1].Trim(), 
					"LAST_MODIFIED=\"[^\"]*\"").ToString();
                lastModified = Regex.Replace(lastModified, 
					"LAST_MODIFIED|\"|=", "");
                //\\
                Writer.WriteStartElement("NODE" + i.ToString());
                Writer.WriteAttributeString("NAME", name);
                Writer.WriteAttributeString("ADD_DATE", addDate);
                Writer.WriteAttributeString("LAST_MODIFIED", lastModified);
                Writer.WriteAttributeString("DESC", desc);
            }
            else if (list[i].Trim() == "</NODE>")
            {
                if (i + 1 != list.Count)
                Writer.WriteEndElement();
            }
            else if (!Regex.IsMatch(list[i + 1], @"\<NODE\>"))
            {
                //bookmark's name extracting
                name = Regex.Match(list[i], "NAME=\"[^\"]*\"").ToString();
                name = Regex.Replace(name, "NAME|\"|=", "");
                //bookmark's address extracting
                href = Regex.Match(list[i].Trim(), 
					"HREF=\"[^\"]*\"").ToString();
                href = Regex.Replace(href, "HREF|\"|=", "");
                //bookmark's icon's URL extracting
                iconUrl = Regex.Match(list[i].Trim(), 
					"ICON_URI=\"[^\"]*\"").ToString();
                iconUrl = Regex.Replace(iconUrl, 
					"ICON_URI|\"|=", "");
                //bookmark's icon extracting
                icon = Regex.Match(list[i].Trim(), 
					"ICON=\"[^\"]*\"").ToString();
                icon = Regex.Replace(icon, 
					"\"|ICON|=", "");
                //bookmark's description extracting
                desc = Regex.Match(list[i].Trim(), 
					"DESC=\"[^\"]*\"").ToString();
                desc = Regex.Replace(desc, "DESC|\"|=", "");
                //bookmark's SHORTCUTURL extracting
                keyWords = Regex.Match(list[i].Trim(), 
					"SHORTCUTURL=\"[^\"]*\"").ToString();
                keyWords = Regex.Replace(keyWords, 
					"SHORTCUTURL|\"|=", "");
                //ADD_DATE
                addDate = Regex.Match(list[i].Trim(), 
					"ADD_DATE=\"[^\"]*\"").ToString();
                addDate = Regex.Replace(addDate, "ADD_DATE|\"|=", "");
                //LAST_MODIFIED
                lastModified = Regex.Match(list[i].Trim(), 
					"LAST_MODIFIED=\"[^\"]*\"").ToString();
                lastModified = Regex.Replace(lastModified, 
					"LAST_MODIFIED|\"|=", "");
                //\\
                /////////////////////////////////////////////////////////////
                //write above data in XML file
                Writer.WriteStartElement("BOOKMARK" + i.ToString());
                Writer.WriteAttributeString("NAME", name.Trim());
                Writer.WriteAttributeString("HREF", href.Trim());
                Writer.WriteAttributeString("SHORTCUTURL", keyWords.Trim());
                Writer.WriteAttributeString("DESC", desc.Trim());
                Writer.WriteAttributeString("ADD_DATE", addDate.Trim());
                Writer.WriteAttributeString("LAST_MODIFIED", lastModified.Trim());
                Writer.WriteAttributeString("ICON_URI", iconUrl.Trim());
                Writer.WriteAttributeString("ICON", icon.Trim());
                Writer.WriteEndElement();
            }
        }
        //Writing close tag for the root element.
        Writer.WriteEndDocument();
        Writer.Flush();
        Writer.Close();
        X_Element = XElement.Load(temporaryFileName);
    }
    catch (Exception ex)
    {
        StackFrame file_info = new StackFrame(true);
        error(ref file_info, ex.Message);
    }
}

XML 文件到 TreeView

创建 XML 文件后,应将 XML 文件加载到 TreeView 控件中。(见下述方法) 如果您在设置中选中“加载图标”,则将显示每个节点的图标。

/// 
/// Converts XML file to treeView
/// 
private void XmlToTree()
{
    optimize_menuItem.Enabled = exportIE_favorites.Enabled = 
			exportXML_menuItem.Enabled =
                            exportHtml_menuItem.Enabled = true;
    this.treeViewBookMark.Enabled = true;
    this.XElementClopboard = null;
    this.TreeNodeClipboard = null;

    try
    {
        // SECTION 1. Create a DOM Document and load the XML data into it.
        XmlDocument dom = new XmlDocument();
        dom.Load(this.temporaryFileName);

        // SECTION 2. Initialize the TreeView control.
        treeViewBookMark.Nodes.Clear();
        treeViewBookMark.Nodes.Add(new TreeNode(dom.DocumentElement.Name));
        TreeNode tNode = new TreeNode(rootNodeName);
        tNode = treeViewBookMark.Nodes[0];
        tNode.Name = rootNodeName;

        // SECTION 3. Populate the TreeView with the DOM nodes.
        AddNode(dom.DocumentElement, tNode);

        treeViewBookMark.SelectedNode = treeViewBookMark.Nodes[0];
        selected_node = treeViewBookMark.Nodes[0];
        treeViewBookMark.SelectedNode.Expand();
    }
    catch (Exception ex)
    {
        textBoxIconURL.Enabled = textBoxDesc.Enabled = textBoxName.Enabled 
			= buttonDelIcon.Enabled = textBoxKeyWords.Enabled 
			= textBoxHref.Enabled = false;
        optimize_menuItem.Enabled = exportIE_favorites.Enabled 
			= exportXML_menuItem.Enabled = exportHtml_menuItem.Enabled
                           = false;
        this.treeViewBookMark.Enabled = false;

        StackFrame file_info = new StackFrame(true);
        error(ref file_info, ex.Message);
        return;
    }
}

/// 
/// Creates treeView
/// References : 
/// ms-help://MS.MSDNQTR.v90.en/enu_kbnetframeworkkb/netframeworkkb/317597.htm
/// http://support.microsoft.com/kb/317597
/// 
private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
{
    try
    {
        XmlNode xNode;
        TreeNode tNode;
        XmlNodeList nodeList;
        int i;
        int j = -1;

        // Loop through the XML nodes until the leaf is reached.
        // Add the nodes to the TreeView during the looping process.
        if (inXmlNode.HasChildNodes)
        {
            nodeList = inXmlNode.ChildNodes;
            for (i = 0; i <= nodeList.Count - 1; i++) 
            {
                if (inXmlNode.ChildNodes[i].Name.Equals("HR"))
                    continue;
                j++;

                xNode = inXmlNode.ChildNodes[i];
                TreeNode newTreeNode;
                newTreeNode = new TreeNode(xNode.Attributes["NAME"].Value);
                newTreeNode.Name = xNode.Name;
                //تعیین عکس هر گره
                //assigns icon of each node -> this code needs more process
                if (loadIcons_menuItem.Checked)
                {
                    Image icon = createIcon(xNode.Name);
                    if (Regex.IsMatch(inXmlNode.ChildNodes[i].Name, "NODE"))
                    {
                        newTreeNode.ImageIndex = 0;
                        newTreeNode.SelectedImageIndex = 0;
                    }
                    else if (icon != null && Regex.IsMatch(inXmlNode.ChildNodes[i].Name,
                        "BOOKMARK"))
                    {
                        imageList1.Images.Add(icon);
                        newTreeNode.ImageIndex = imageList1.Images.Count - 1;
                        newTreeNode.SelectedImageIndex = imageList1.Images.Count - 1;
                    }
                    else
                    {
                        newTreeNode.ImageIndex = 1;
                        newTreeNode.SelectedImageIndex = 1;
                    }
                }
                else
                {
                    if (Regex.IsMatch(inXmlNode.ChildNodes[i].Name, "NODE"))
                    {
                        newTreeNode.ImageIndex = 0;
                        newTreeNode.SelectedImageIndex = 0;
                    }
                    else if (Regex.IsMatch(inXmlNode.ChildNodes[i].Name, "BOOKMARK"))
                    {
                        newTreeNode.ImageIndex = 1;
                        newTreeNode.SelectedImageIndex = 1;
                    }
                }
                //\\
                inTreeNode.Nodes.Add(newTreeNode);
                tNode = inTreeNode.Nodes[j];
                AddNode(xNode, tNode);
            }
        }
        else
        {
            // Here you need to pull the data from the XmlNode based on the
            // type of node, whether attribute values are required, and so forth.
            inTreeNode.Text = (inXmlNode.Attributes["NAME"].Value).Trim();
        }
    }
    catch (Exception ex)
    {
        textBoxIconURL.Enabled = textBoxDesc.Enabled = 
				textBoxName.Enabled = buttonDelIcon.Enabled = 
				textBoxKeyWords.Enabled = textBoxHref.Enabled =
                                     false;
        optimize_menuItem.Enabled = exportIE_favorites.Enabled = 
				exportXML_menuItem.Enabled =
                                     exportHtml_menuItem.Enabled = false;
        treeViewBookMark.Nodes.Clear();
        this.treeViewBookMark.Enabled = false;

        StackFrame file_info = new StackFrame(true);
        error(ref file_info, ex.Message);
        return;
    }
}

KingMark 功能

TreeView 拖放

您可以直接导出 IE 收藏夹文件,使用拖动 TreeView 文件夹或文件到窗口。

与上述不同的是,您可以将 IE 收藏夹文件拖到 KingMark 的 TreeView 中来导入它们。

此外,您还可以将 IE6(我有 IE6,可能在 IE7 或 IE8 上不起作用)网站地址和 FF3(我有 FF3,可能在 FF2 或 FF1 上不起作用)网站标签拖入 KingMark 的 TreeView 控件中。

  

为 Internet Explorer 或 Firefox 浏览器导出书签

使用 KingMark,您可以为 FF (HTML 文件) 或 IE (*.url 文件) 导出所有或部分书签

要导出所有书签,请使用“导出”菜单

要导出部分书签,请使用 TreeView 的 contextMenuStrip

导出到 FF
导出到 IE

快速搜索


Searching Firefox bookmark manager

我使用 LINQ 来搜索 XML 文件(见下述方法)

private void textBoxSearchTxt_TextChanged(object sender, EventArgs e)
{
    string searchTxt = Regex.Replace(textBoxSearchTxt.Text.Trim(),
        @"[\$\^\{\[\(\|\)\*\+\?\\]", "");
    if (searchTxt == "")
    {
        this.listView1.Items.Clear();
        return;
    }
    try
    {
        var searchNodes = from nodes in X_Element.Descendants()
                          where
                          (nodes.Attribute("NAME") != null    
                          Regex.IsMatch(nodes.Attribute("NAME").Value, 
                          	searchTxt, RegexOptions.IgnoreCase))
                           || (nodes.Attribute("HREF") != null    
                           Regex.IsMatch(nodes.Attribute("HREF").Value, searchTxt, 
                          	 RegexOptions.IgnoreCase))
                           || (nodes.Attribute("SHORTCUTURL") != null    
                           Regex.IsMatch(nodes.Attribute("SHORTCUTURL").Value,
                               searchTxt, 
                           	RegexOptions.IgnoreCase))
                          select nodes;

        listView1.Items.Clear();

        foreach (var node in searchNodes)
        {
            try
            {
                ListViewItem item = new ListViewItem(new string[] 
                { node.Attribute("NAME").Value, node.Attribute("HREF").Value });
                item.Name = node.Name.ToString();
                listView1.Items.Add(item);
            }
            catch
            {
                continue;
            }
        }
    }
    catch { }
}

生成网站预览图像

您可以在我的项目中找到 WebsiteThumbnailImage.cs,并了解我是如何做到的。
Firefox bookmark manager

通知图标

当您最小化 KingMark 窗口时,KingMark 会创建一个带有 TreeView 节点的 contextMenuStrip 并在其中显示一个 notifyIcon

并且您可以轻松访问您的书签

我们如何将 TreeView 转换为 contextMenuStrip

我编写了这些方法来执行此操作,并且这些方法运行良好。但是,如果您有更好的方法,如果您告诉我,我将感谢您。

void createContextMenuStripNotifyIcon()
{
    try
    {
        if (this.treeViewBookMark.Nodes.Count <= 0) return;
        contextMenuStripNotifyIcon.Items.Clear();
        foreach (TreeNode node in this.treeViewBookMark.Nodes[0].Nodes)
        {
            ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem();
            if (node.GetNodeCount(true) > 0)
            {
                toolStripMenuItem.BackColor = contextMenuStripNotifyIcon.BackColor;
                toolStripMenuItem.Image = imageList1.Images[node.ImageIndex];
                toolStripMenuItem.Text = node.Text.Length > 30 ? 
                	node.Text.Substring(0, 30) + " ..." : node.Text;
                toolStripMenuItem.Name = node.Name;
                createContextMenuStripNotifyIcon(node, ref toolStripMenuItem);
                contextMenuStripNotifyIcon.Items.Add(toolStripMenuItem);
            }
            else
            {
                toolStripMenuItem.BackColor = contextMenuStripNotifyIcon.BackColor;
                toolStripMenuItem.Image = imageList1.Images[node.ImageIndex];
                toolStripMenuItem.Text = node.Text.Length > 30 ? 
                	node.Text.Substring(0, 30) + " ..." : node.Text;
                toolStripMenuItem.Name = node.Name;
                toolStripMenuItem.MouseDown += 
                	new MouseEventHandler(contextMenuStripNotifyIconItems_MouseDown);
                contextMenuStripNotifyIcon.Items.Add(toolStripMenuItem);
            }
        }
    }
    catch (Exception ex)
    {
        StackFrame file_info = new StackFrame(true);
        error(ref file_info, ex.Message);
    }
}

void createContextMenuStripNotifyIcon(TreeNode nodes,
    ref ToolStripMenuItem toolStripMenuItem)
{
    foreach (TreeNode node in nodes.Nodes)
    {
        if (node.GetNodeCount(true) > 0)
        {
            ToolStripMenuItem newToolStripMenuItem = new ToolStripMenuItem();
            newToolStripMenuItem.BackgroundImage = imageList1.Images[node.ImageIndex];
            newToolStripMenuItem.BackgroundImageLayout = ImageLayout.None;
            newToolStripMenuItem.Text = node.Text.Length > 30 ? 
            	node.Text.Substring(0, 30) + " ..." : node.Text;
            newToolStripMenuItem.Name = node.Name;
            createContextMenuStripNotifyIcon(node, ref newToolStripMenuItem);
            toolStripMenuItem.DropDown.Items.Add(newToolStripMenuItem);
        }
        else
        {
            ToolStripMenuItem newToolStripMenuItem = new ToolStripMenuItem();
            newToolStripMenuItem.BackgroundImage = imageList1.Images[node.ImageIndex];
            newToolStripMenuItem.BackgroundImageLayout = ImageLayout.None;
            newToolStripMenuItem.Text = node.Text.Length > 30 ? 
            	node.Text.Substring(0, 30) + " ..." : node.Text;
            newToolStripMenuItem.Name = node.Name;
            newToolStripMenuItem.MouseDown += 
            	new MouseEventHandler(contextMenuStripNotifyIconItems_MouseDown);
            toolStripMenuItem.DropDown.Items.Add(newToolStripMenuItem);
        }
    }
}

void contextMenuStripNotifyIconItems_MouseDown(object sender, MouseEventArgs e)
{
    try
    {
        if (e.Button == MouseButtons.Left)
            Process.Start(GetHref(((ToolStripMenuItem)sender).Name));
    }
    catch
    {
        StackFrame file_info = new StackFrame(true);
        error(ref file_info, "Invalid URL");
    }
}
© . All rights reserved.