private void AttachmentExport(ExportExcludeType exclude, PageBE page, ResourceBE file)
        {
            // Export the file
            if (!_uris.ContainsKey(AttachmentBL.Instance.GetUriContent(file)))
            {
                _uris.Add(AttachmentBL.Instance.GetUriContent(file), null);
                XDoc manifestDoc = new XDoc("file").Elem("filename", file.Name)
                                   .Elem("path", page.Title.AsRelativePath(_relToTitle))
                                   .Start("contents").Attr("type", file.MimeType.ToString()).End();
                Add(AttachmentBL.Instance.GetUriContent(file), manifestDoc);
            }

            // Export the file properties (if not excluded)
            if (ExportExcludeType.NONE == (ExportExcludeType.PROPS & exclude))
            {
                IList <ResourceBE> properties = PropertyBL.Instance.GetAttachmentProperties(file.ResourceId);
                foreach (ResourceBE property in properties)
                {
                    PropertyExport(page, file, property);
                }
            }
        }
        //--- Methods ---
        public void Append(XDoc exportDoc)
        {
            _manifestDoc.Attr("date.created", DateTime.UtcNow).Attr("preserve-local", false);
            foreach (XDoc exportXml in exportDoc.Elements)
            {
                // Retrieve the current page
                try {
                    if (exportXml.HasName("page"))
                    {
                        // Generate the manifest and request needed to export the page
                        PageBE page = null;
                        if (!exportXml["@id"].IsEmpty)
                        {
                            uint pageId = DbUtils.Convert.To <uint>(exportXml["@id"].Contents, 0);
                            if (0 < pageId)
                            {
                                page = PageBL.GetPageById(pageId);
                            }
                        }
                        else if (!exportXml["@path"].IsEmpty)
                        {
                            page = PageBL.GetPageByTitle(Title.FromPrefixedDbPath(exportXml["@path"].Contents, null));
                        }
                        if ((null == page) || (0 == page.ID))
                        {
                            throw new PageNotFoundException();
                        }

                        // Check whether to exclude subpages, files, and/or properties
                        bool recursive            = exportXml["@recursive"].AsBool ?? false;
                        ExportExcludeType exclude = ExportExcludeType.NONE;
                        if (!exportXml["@exclude"].IsEmpty)
                        {
                            exclude = SysUtil.ChangeType <ExportExcludeType>(exportXml["@exclude"].Contents);
                        }

                        // Export the page
                        PageExport(recursive, exclude, page);
                    }
                    else if (exportXml.HasName("file"))
                    {
                        // Generate the manifest and request needed to export the file
                        ResourceBE file = null;
                        if (!exportXml["@id"].IsEmpty)
                        {
                            uint fileId = DbUtils.Convert.To <uint>(exportXml["@id"].Contents, 0);
                            if (0 < fileId)
                            {
                                uint resourceId = ResourceMapBL.GetResourceIdByFileId(fileId) ?? 0;
                                if (resourceId > 0)
                                {
                                    file = ResourceBL.Instance.GetResource(resourceId);
                                }
                            }
                        }
                        if (null == file)
                        {
                            throw new AttachmentNotFoundException();
                        }

                        // Check whether to exclude properties
                        ExportExcludeType exclude = ExportExcludeType.NONE;
                        if (!exportXml["@exclude"].IsEmpty)
                        {
                            exclude = SysUtil.ChangeType <ExportExcludeType>(exportXml["@exclude"].Contents);
                        }

                        // Perform the file export
                        PageBE page = PageBL.GetPageById(file.ParentPageId.Value);
                        page = PageBL.AuthorizePage(DekiContext.Current.User, Permissions.READ, page, false);
                        AttachmentExport(exclude, page, file);
                    }
                    else
                    {
                        throw new DreamResponseException(DreamMessage.NotImplemented(exportXml.Name));
                    }
                } catch (ResourcedMindTouchException e) {
                    AddError(e.Message, (int)e.Status, exportXml);
                } catch (DreamAbortException e) {
                    AddError(e.Message, (int)e.Response.Status, exportXml);
                } catch (Exception e) {
                    AddError(e.Message, (int)DreamStatus.InternalError, exportXml);
                }
            }
        }
        private void AttachmentExport(ExportExcludeType exclude, PageBE page, AttachmentBE file) {

            // Export the file
            if(!_uris.ContainsKey(AttachmentBL.Instance.GetUriContent(file))) {
                _uris.Add(AttachmentBL.Instance.GetUriContent(file), null);
                XDoc manifestDoc = new XDoc("file").Elem("filename", file.Name)
                                                   .Elem("path", page.Title.AsRelativePath(_relToTitle))
                                                   .Start("contents").Attr("type", file.MimeType.ToString()).End();
                Add(AttachmentBL.Instance.GetUriContent(file), manifestDoc);
            }

            // Export the file properties (if not excluded)
            if(ExportExcludeType.NONE == (ExportExcludeType.PROPS & exclude)) {
                IList<PropertyBE> properties = PropertyBL.Instance.GetResources(file.ResourceId, ResourceBE.Type.FILE, null, DeletionFilter.ACTIVEONLY);
                foreach(PropertyBE property in properties) {
                    PropertyExport(page, file, property);
                }
            }
        }
        private void PageExport(bool recursive, ExportExcludeType exclude, PageBE page)
        {
            // Validate the page export
            page = PageBL.AuthorizePage(DekiContext.Current.User, Permissions.READ, page, false);
            if (page.IsRedirect)
            {
                throw new SiteExportRedirectInvalidOperationException();
            }

            // Export the page
            XUri uri = PageBL.GetUriCanonical(page).At("contents")
                       .With("mode", "edit")
                       .With("reltopath", _relToTitle.AsPrefixedDbPath())
                       .With("format", "xhtml");

            if (!_uris.ContainsKey(uri))
            {
                _uris.Add(uri, null);
                var dateModified = page.TimeStamp;
                var lastImport   = PropertyBL.Instance.GetPageProperty((uint)page.ID, SiteImportBuilder.LAST_IMPORT);
                if (lastImport != null)
                {
                    var content   = lastImport.Content;
                    var importDoc = XDocFactory.From(content.ToStream(), content.MimeType);
                    if (importDoc["etag"].AsText.EqualsInvariant(page.Etag))
                    {
                        dateModified = importDoc["date.modified"].AsDate ?? DateTime.MinValue;
                    }
                }
                var manifestDoc = new XDoc("page").Elem("title", page.Title.DisplayName)
                                  .Elem("path", page.Title.AsRelativePath(_relToTitle))
                                  .Elem("language", page.Language)
                                  .Elem("etag", page.Etag)
                                  .Elem("date.modified", dateModified.ToSafeUniversalTime())
                                  .Start("contents").Attr("type", page.ContentType).End();
                Add(uri, manifestDoc);
            }

            // Export page tags (if not excluded)
            if (ExportExcludeType.NONE == (ExportExcludeType.TAGS & exclude))
            {
                XUri tagUri = PageBL.GetUriCanonical(page).At("tags");
                if (!_uris.ContainsKey(tagUri))
                {
                    _uris.Add(tagUri, null);
                    XDoc manifestDoc = new XDoc("tags").Elem("path", page.Title.AsRelativePath(_relToTitle));
                    Add(tagUri, manifestDoc);
                }
            }

            // Export page properties (if not excluded)
            if (ExportExcludeType.NONE == (ExportExcludeType.PROPS & exclude))
            {
                IList <ResourceBE> properties = PropertyBL.Instance.GetPageProperties(page.ID);
                foreach (ResourceBE property in properties)
                {
                    if (property.Name.EqualsInvariant(SiteImportBuilder.LAST_IMPORT))
                    {
                        continue;
                    }
                    PropertyExport(page, null, property);
                }
            }

            // Export page files (if not excluded)
            if (ExportExcludeType.NONE == (ExportExcludeType.FILES & exclude))
            {
                IList <ResourceBE> files = AttachmentBL.Instance.GetPageAttachments(page.ID);
                foreach (ResourceBE file in files)
                {
                    AttachmentExport(exclude, page, file);
                }
            }

            // Export talk page (if not excluded)
            if ((ExportExcludeType.NONE == (ExportExcludeType.TALK & exclude)) && (!page.Title.IsTalk))
            {
                PageBE talkPage = PageBL.GetPageByTitle(page.Title.AsTalk());
                if ((null != talkPage) && (0 < talkPage.ID))
                {
                    PageExport(false, exclude, talkPage);
                }
            }

            // Export subpages (if not excluded)
            if (recursive)
            {
                ICollection <PageBE> children = PageBL.GetChildren(page, true);
                children = PermissionsBL.FilterDisallowed(DekiContext.Current.User, PageBL.GetChildren(page, true), false, Permissions.READ);
                if (children != null)
                {
                    foreach (PageBE child in children)
                    {
                        PageExport(recursive, exclude, child);
                    }
                }
            }
        }
        private void PageExport(bool recursive, ExportExcludeType exclude, PageBE page) {

            // Validate the page export
            page = PageBL.AuthorizePage(DekiContext.Current.User, Permissions.READ, page, false);
            if(page.IsRedirect) {
                throw new DreamBadRequestException(DekiResources.INVALID_REDIRECT_OPERATION);
            }

            // Export the page
            XUri uri = PageBL.GetUriCanonical(page).At("contents")
                                        .With("mode", "edit")
                                        .With("reltopath", _relToTitle.AsPrefixedDbPath())
                                        .With("format", "xhtml");
            if(!_uris.ContainsKey(uri)) {
                _uris.Add(uri, null);
                var dateModified = page.TimeStamp;
                var lastImport = PropertyBL.Instance.GetResource((uint)page.ID, ResourceBE.Type.PAGE, SiteImportBuilder.LAST_IMPORT);
                if(lastImport != null) {
                    var content = lastImport.Content;
                    var importDoc = XDocFactory.From(content.ToStream(), content.MimeType);
                    if(importDoc["etag"].AsText.EqualsInvariant(page.Etag)) {
                        dateModified = importDoc["date.modified"].AsDate ?? DateTime.MinValue;
                    }
                }
                var manifestDoc = new XDoc("page").Elem("title", page.Title.DisplayName)
                                                   .Elem("path", page.Title.AsRelativePath(_relToTitle))
                                                   .Elem("language", page.Language)
                                                   .Elem("etag", page.Etag)
                                                   .Elem("date.modified", dateModified.ToSafeUniversalTime())
                                                   .Start("contents").Attr("type", page.ContentType).End();
                Add(uri, manifestDoc);
            }

            // Export page tags (if not excluded)
            if(ExportExcludeType.NONE == (ExportExcludeType.TAGS & exclude)) {
                XUri tagUri = PageBL.GetUriCanonical(page).At("tags");
                if(!_uris.ContainsKey(tagUri)) {
                    _uris.Add(tagUri, null);
                    XDoc manifestDoc = new XDoc("tags").Elem("path", page.Title.AsRelativePath(_relToTitle));
                    Add(tagUri, manifestDoc);
                }
            }

            // Export page properties (if not excluded)
            if(ExportExcludeType.NONE == (ExportExcludeType.PROPS & exclude)) {
                IList<PropertyBE> properties = PropertyBL.Instance.GetResources((uint)page.ID, ResourceBE.Type.PAGE, null, DeletionFilter.ACTIVEONLY);
                foreach(PropertyBE property in properties) {
                    if(property.Name.EqualsInvariant(SiteImportBuilder.LAST_IMPORT)) {
                        continue;
                    }
                    PropertyExport(page, null, property);
                }
            }

            // Export page files (if not excluded)
            if(ExportExcludeType.NONE == (ExportExcludeType.FILES & exclude)) {
                IList<AttachmentBE> files = AttachmentBL.Instance.GetResources(page, DeletionFilter.ACTIVEONLY);
                foreach(AttachmentBE file in files) {
                    AttachmentExport(exclude, page, file);
                }
            }

            // Export talk page (if not excluded)
            if((ExportExcludeType.NONE == (ExportExcludeType.TALK & exclude)) && (!page.Title.IsTalk)) {
                PageBE talkPage = PageBL.GetPageByTitle(page.Title.AsTalk());
                if((null != talkPage) && (0 < talkPage.ID)) {
                    PageExport(false, exclude, talkPage);
                }
            }

            // Export subpages (if not excluded)
            if(recursive) {
                ICollection<PageBE> children = PageBL.GetChildren(page, true);
                children = PermissionsBL.FilterDisallowed(DekiContext.Current.User, PageBL.GetChildren(page, true), false, Permissions.READ);
                if(children != null) {
                    foreach(PageBE child in children) {
                        PageExport(recursive, exclude, child);
                    }
                }
            }
        }