text:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Diagnostics;

namespace DigitalPlatform.Xml
{
    // DomUtil类包含XML DOM的一些扩展功能函数
    public class DomUtil
    {
        // parameters:
        //      condition   如果为 "element_not_exists",表示元素一开始不存在
        //      action      希望进行的动作。传入值为 "change" 或者 "remove"。传出值表示希望进行的修改动作
        public delegate void FuncChange(string condition,
            ref string action,
            ref string attr_value);

        // 有条件地修改一个元素的属性值。
        // 所谓条件就是根据 func 的返回值判断
        // parameters:
        //      element_name    内容为 "element1/element2" 形态
        public static bool ChangeAttribute(XmlDocument dom,
            string element_name,
            string attr_name,
            FuncChange func)
        {
            bool bChanged = false;
            string attr_value = null;
            string action = "change";
            string strOldValue = null;

            XmlElement element = dom.DocumentElement.SelectSingleNode(element_name) as XmlElement;
            if (element == null)
            {
                func("element_not_exists", ref action, ref attr_value);
                if (attr_value == null || action == "remove")
                    return false;
                element = DomUtil.CreateNode(dom.DocumentElement, element_name.Split(new char[] { '/' })) as XmlElement;
                bChanged = true;
            }
            else
            {
                attr_value = element.GetAttribute(attr_name);
                strOldValue = attr_value;
                func("element_exists", ref action, ref attr_value);
            }

            if (attr_value == null && strOldValue == null)
                return bChanged;
            if (attr_value == null || action == "remove")
                element.RemoveAttribute(attr_name);
            else
            {
                if (attr_value == strOldValue)
                    return bChanged;
                element.SetAttribute(attr_name, attr_value);
            }

            bChanged = true;
            return bChanged;
        }

        // 确保在根元素之下创建一个容器元素
        public static XmlElement EnsureContainerElement(XmlDocument cfg_dom,
            string strElementName)
        {
            XmlElement container = cfg_dom.DocumentElement.SelectSingleNode(strElementName) as XmlElement;
            if (container == null)
            {
                container = cfg_dom.CreateElement(strElementName);
                cfg_dom.DocumentElement.AppendChild(container);
            }

            return container;
        }

        // 2017/12/27
        public static void SafeLoadXml(XmlDocument dom, string xml)
        {
            dom.LoadXml(string.IsNullOrEmpty(xml) ? "<root />" : xml);
        }

        public static string RemoveEmptyElements(string strXml)
        {
            if (String.IsNullOrEmpty(strXml) == true)
                return strXml;

            XmlDocument dom = new XmlDocument();
            try
            {
                dom.LoadXml(strXml);
            }
            catch
            {
                return strXml;
            }

            if (dom.DocumentElement == null)
                return strXml;

            RemoveEmptyElements(dom.DocumentElement);

            return dom.DocumentElement.OuterXml;
        }

        // 删除 start 元素下的所有空元素
        // parameters:
        //      bCheckStart 是否检查 start 节点的状况。如果本参数为 true, 当 start 为空元素时,要删除 start 元素
        public static void RemoveEmptyElements(XmlElement start,
            bool bCheckStart = false)
        {
            List<XmlElement> delete = new List<XmlElement>();
            foreach (XmlNode node in start.ChildNodes)
            {
                if (node.NodeType != XmlNodeType.Element)
                    continue;
                XmlElement element = node as XmlElement;
                if (element.HasAttributes == false
                    && string.IsNullOrEmpty(element.InnerXml.Trim()) == true)
                {
                    delete.Add(element);
                }
                else
                    RemoveEmptyElements(element, true);
            }

            foreach (XmlElement element in delete)
            {
                element.ParentNode.RemoveChild(element);
            }

            if (bCheckStart == true && start.ParentNode != null)
            {
                XmlElement element = start;
                if (element.HasAttributes == false
                    && string.IsNullOrEmpty(element.InnerXml.Trim()) == true)
                    element.ParentNode.RemoveChild(element);
            }
        }

        public static XmlNode RenameNode(XmlNode node,
            string namespaceURI,
            string qualifiedName)
        {
            if (node.NodeType == XmlNodeType.Element)
            {
                XmlElement oldElement = (XmlElement)node;
                XmlElement newElement =
                node.OwnerDocument.CreateElement(qualifiedName, namespaceURI);

                while (oldElement.HasAttributes)
                {
                    newElement.SetAttributeNode(oldElement.RemoveAttributeNode(oldElement.Attributes[0]));
                }

                while (oldElement.HasChildNodes)
                {
                    newElement.AppendChild(oldElement.FirstChild);
                }

                if (oldElement.ParentNode != null)
                {
                    oldElement.ParentNode.ReplaceChild(newElement, oldElement);
                }

                return newElement;
            }
            else
            {
                return null;
            }
        }

        // 2010/12/18
        // 从一个元素的下级的多个<strElementName>元素中, 提取语言符合的XmlNode的InnerText
        // parameters:
        //      bReturnFirstNode    如果找不到相关语言的,是否返回第一个<strElementName>
        public static string GetLangedNodeText(
            string strLang,
            XmlNode parent,
            string strElementName,
            bool bReturnFirstNode = true)
        {
            XmlNode node = GetLangedNode(
        strLang,
        parent,
        strElementName,
        bReturnFirstNode);
            if (node == null)
                return null;
            return node.InnerText;
        }

        // 2010/12/18
        // 从一个元素的下级的多个<strElementName>元素中, 提取语言符合的XmlNode
        // parameters:
        //      bReturnFirstNode    如果找不到相关语言的,是否返回第一个<strElementName>
        public static XmlNode GetLangedNode(
            string strLang,
            XmlNode parent,
            string strElementName,
            bool bReturnFirstNode = true)
        {
            XmlNode node = null;

            if (String.IsNullOrEmpty(strLang) == true)
            {
                return parent.SelectSingleNode(strElementName);  // 第一个strElementName元素
            }
            else
            {
                node = parent.SelectSingleNode(strElementName + "[@lang='" + strLang + "']");

                if (node != null)
                    return node;
            }

            string strLangLeft = "";
            string strLangRight = "";

            SplitLang(strLang,
               out strLangLeft,
               out strLangRight);

            // 所有<caption>元素
            XmlNodeList nodes = parent.SelectNodes(strElementName);

            for (int i = 0; i < nodes.Count; i++)
            {
                string strThisLang = DomUtil.GetAttr(nodes[i], "lang");

                string strThisLangLeft = "";
                string strThisLangRight = "";

                SplitLang(strThisLang,
                   out strThisLangLeft,
                   out strThisLangRight);

                // 是不是左右都匹配则更好?如果不行才是第一个左边匹配的

                if (strThisLangLeft == strLangLeft)
                    return nodes[i];
            }

            if (bReturnFirstNode == true)
            {
                // 实在不行,则选第一个<caption>的文字值
                node = parent.SelectSingleNode(strElementName);
                if (node != null)
                    return node;
            }

            return null;    // not found
        }

        // 从一个元素的下级的多个<strElementName>元素中, 提取语言符合的XmlNode的InnerText
        // parameters:
        //      bReturnFirstNode    如果找不到相关语言的,是否返回第一个<strElementName>
        public static string GetXmlLangedNodeText(
            string strLang,
            XmlNode parent,
            string strElementName,
            bool bReturnFirstNode = true)
        {
            XmlNode node = GetXmlLangedNode(
        strLang,
        parent,
        strElementName,
        bReturnFirstNode);
            if (node == null)
                return null;
            return node.InnerText;
        }

        // 从一个元素的下级的多个<strElementName>元素中, 提取语言符合的XmlNode
        // parameters:
        //      bReturnFirstNode    如果找不到相关语言的,是否返回第一个<strElementName>
        public static XmlNode GetXmlLangedNode(
            string strLang,
            XmlNode parent,
            string strElementName,
            bool bReturnFirstNode = true)
        {
            XmlNode node = null;

            if (String.IsNullOrEmpty(strLang) == true)
            {
                return parent.SelectSingleNode(strElementName);  // 第一个strElementName元素
            }
            else
            {
                XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
                nsmgr.AddNamespace("xml", Ns.xml);

                node = parent.SelectSingleNode(strElementName + "[@xml:lang='" + strLang + "']", nsmgr);

                if (node != null)
                    return node;
            }

            string strLangLeft = "";
            string strLangRight = "";

            SplitLang(strLang,
               out strLangLeft,
               out strLangRight);

            // 所有<strElementName>元素
            XmlNodeList nodes = parent.SelectNodes(strElementName);

            for (int i = 0; i < nodes.Count; i++)
            {
                string strThisLang = DomUtil.GetAttr(Ns.xml, nodes[i], "lang");

                string strThisLangLeft = "";
                string strThisLangRight = "";

                SplitLang(strThisLang,
                   out strThisLangLeft,
                   out strThisLangRight);

                // 是不是左右都匹配则更好?如果不行才是第一个左边匹配的

                if (strThisLangLeft == strLangLeft)
                    return nodes[i];
            }

            if (bReturnFirstNode == true)
            {
                // 实在不行,则选第一个<strElementName>的文字值
                node = parent.SelectSingleNode(strElementName);
                if (node != null)
                    return node;
            }

            return null;    // not found
        }

        // 从一个元素的下级<caption>元素中, 提取语言符合的文字值
        // 和GetCaption()函数的差异,在于如果找不到相关语言的,不做返回第一个<caption>
        public static string GetCaptionExt(string strLang,
            XmlNode parent)
        {
            XmlNode node = null;

            if (String.IsNullOrEmpty(strLang) == true)
            {
                node = parent.SelectSingleNode("caption");  // 第一个caption元素
                if (node != null)
                    return node.InnerText;

                return null;
            }
            else
            {
                node = parent.SelectSingleNode("caption[@lang='" + strLang + "']");

                if (node != null)
                    return node.InnerText;
            }

            string strLangLeft = "";
            string strLangRight = "";

            SplitLang(strLang,
               out strLangLeft,
               out strLangRight);

            // 所有<caption>元素
            XmlNodeList nodes = parent.SelectNodes("caption");

            for (int i = 0; i < nodes.Count; i++)
            {
                string strThisLang = DomUtil.GetAttr(nodes[i], "lang");

                string strThisLangLeft = "";
                string strThisLangRight = "";

                SplitLang(strThisLang,
                   out strThisLangLeft,
                   out strThisLangRight);

                // 是不是左右都匹配则更好?如果不行才是第一个左边匹配的

                if (strThisLangLeft == strLangLeft)
                    return nodes[i].InnerText;
            }

            /*
            // 实在不行,则选第一个<caption>的文字值
            node = parent.SelectSingleNode("caption");
            if (node != null)
                return node.InnerText;
             * */

            return null;    // not found
        }

        // 从一个元素的下级<caption>元素中, 提取语言符合的文字值
        public static string GetCaption(string strLang,
            XmlNode parent)
        {
            XmlNode node = null;

            if (String.IsNullOrEmpty(strLang) == true)
            {
                node = parent.SelectSingleNode("caption");  // 第一个caption元素
                if (node != null)
                    return node.InnerText;

                return null;
            }
            else
            {
                node = parent.SelectSingleNode("caption[@lang='" + strLang + "']");

                if (node != null)
                    return node.InnerText;
            }

            string strLangLeft = "";
            string strLangRight = "";

            SplitLang(strLang,
               out strLangLeft,
               out strLangRight);

            // 所有<caption>元素
            XmlNodeList nodes = parent.SelectNodes("caption");

            for (int i = 0; i < nodes.Count; i++)
            {
                string strThisLang = DomUtil.GetAttr(nodes[i], "lang");

                string strThisLangLeft = "";
                string strThisLangRight = "";

                SplitLang(strThisLang,
                   out strThisLangLeft,
                   out strThisLangRight);

                // 是不是左右都匹配则更好?如果不行才是第一个左边匹配的

                if (strThisLangLeft == strLangLeft)
                    return nodes[i].InnerText;
            }

            // 实在不行,则选第一个<caption>的文字值
            node = parent.SelectSingleNode("caption");
            if (node != null)
                return node.InnerText;

            return null;    // not found
        }

        public static void SplitLang(string strLang,
    out string strLangLeft,
    out string strLangRight)
        {
            strLangLeft = "";
            strLangRight = "";

            int nRet = strLang.IndexOf("-");
            if (nRet == -1)
                strLangLeft = strLang;
            else
            {
                strLangLeft = strLang.Substring(0, nRet);
                strLangRight = strLang.Substring(nRet + 1);
            }
        }

        // 把表示布尔值的字符串翻译为布尔值
        // 注意,strValue不能为空,本函数无法解释缺省值
        public static bool IsBooleanTrue(string strValue)
        {
            // 2008/6/4
            if (String.IsNullOrEmpty(strValue) == true)
                throw new Exception("DomUtil.IsBoolean() 不能接受空字符串参数");

            strValue = strValue.ToLower();  // 2008/6/4

            if (strValue == "yes" || strValue == "on"
                    || strValue == "1" || strValue == "true")
                return true;

            return false;
        }

        public static bool IsBooleanTrue(string strValue, bool bDefaultValue)
        {
            if (string.IsNullOrEmpty(strValue) == true)
                return bDefaultValue;
            return IsBooleanTrue(strValue);
        }

        // 包装版本
        public static bool GetBooleanParam(XmlNode node,
            string strParamName,
            bool bDefaultValue)
        {
            bool bValue = bDefaultValue;
            string strError = "";
            GetBooleanParam(node,
                strParamName,
                bDefaultValue,
                out bValue,
                out strError);
            return bValue;
        }

        // 包装后的版本。不用事先获得元素的 Node
        public static bool GetBooleanParam(
            XmlNode root,
            string strElementPath,
            string strParamName,
            bool bDefaultValue)
        {
            XmlNode node = root.SelectSingleNode(strElementPath);
            if (node == null)
                return bDefaultValue;
            return GetBooleanParam(node,
                strParamName,
                bDefaultValue);
        }

        // 设置 bool 类型的参数
        // parameters:
        //      root    起点 XmlNode
        //      strElementPath  元素路径
        //      strParamName    属性名
        //      bValue  要设置的值
        // return:
        //      本次是否创建了新的元素
        public static bool SetBooleanParam(
            XmlNode root,
            string strElementPath,
            string strParamName,
            bool bValue)
        {
            bool bCreateElement = false;
            XmlNode node = root.SelectSingleNode(strElementPath);
            if (node == null)
            {
                string[] aNodeName = strElementPath.Split(new Char[] { '/' });
                node = CreateNode(root, aNodeName);
                bCreateElement = true;
            }
            if (node == null)
            {
                throw (new Exception("SetBooleanParam() CreateNode error"));
            }

            SetAttr(node, strParamName, bValue == true ? "true" : "false");
            return bCreateElement;
        }

        // 获得布尔型的属性参数值
        // return:
        //      -1  出错。但是bValue中已经有了bDefaultValue值,可以不加警告而直接使用
        //      0   正常获得明确定义的参数值
        //      1   参数没有定义,因此代替以缺省参数值返回
        public static int GetBooleanParam(XmlNode node,
            string strParamName,
            bool bDefaultValue,
            out bool bValue,
            out string strError)
        {
            strError = "";
            bValue = bDefaultValue;

            string strValue = DomUtil.GetAttr(node, strParamName);

            strValue = strValue.Trim();

            if (String.IsNullOrEmpty(strValue) == true)
            {
                bValue = bDefaultValue;
                return 1;
            }

            strValue = strValue.ToLower();

            if (strValue == "yes" || strValue == "on"
                || strValue == "1" || strValue == "true")
            {
                bValue = true;
                return 0;
            }

            // TODO: 可以检查字符串,要在规定的值范围内

            bValue = false;
            return 0;
        }

        // 2016/10/13
        // 包装版本
        public static string GetStringParam(XmlElement node,
            string strParamName,
            string strDefaultValue)
        {
            string strValue = strDefaultValue;
            string strError = "";
            GetStringParam(node,
                strParamName,
                strDefaultValue,
                out strValue,
                out strError);
            return strValue;
        }

        // 2016/10/13
        // 包装后的版本。不用事先获得元素的 Node
        public static string GetStringParam(
            XmlNode root,
            string strElementPath,
            string strParamName,
            string strDefaultValue)
        {
            XmlElement node = root.SelectSingleNode(strElementPath) as XmlElement;
            if (node == null)
                return strDefaultValue;
            return GetStringParam(node,
                strParamName,
                strDefaultValue);
        }

        // 2016/10/13
        // 获得字符串的属性参数值
        // 注:属性节点不具备的时候,返回 strDefaultValue。否则,就要返回属性值,哪怕属性值为 ""
        // return:
        //      -1  出错。但是nValue中已经有了nDefaultValue值,可以不加警告而直接使用
        //      0   正常获得明确定义的参数值
        //      1   参数没有定义,因此代替以缺省参数值返回
        public static int GetStringParam(XmlElement node,
            string strParamName,
            string strDefaultValue,
            out string strValue,
            out string strError)
        {
            strError = "";

            XmlAttribute attr = node.GetAttributeNode(strParamName);
            if (attr == null)
            {
                strValue = strDefaultValue;
                return 1;
            }
            strValue = attr.Value;
            if (string.IsNullOrEmpty(strValue) == false)
                strValue = strValue.Trim();

            return 0;
        }

        // 获得整数型的属性参数值
        // return:
        //      -1  出错。但是nValue中已经有了nDefaultValue值,可以不加警告而直接使用
        //      0   正常获得明确定义的参数值
        //      1   参数没有定义,因此代替以缺省参数值返回
        public static int GetIntegerParam(XmlNode node,
            string strParamName,
            int nDefaultValue,
            out int nValue,
            out string strError)
        {
            strError = "";
            nValue = nDefaultValue;

            string strValue = DomUtil.GetAttr(node, strParamName);

            if (String.IsNullOrEmpty(strValue) == true)
            {
                nValue = nDefaultValue;
                return 1;
            }

            try
            {
                nValue = Convert.ToInt32(strValue);
            }
            catch (Exception ex)
            {
                strError = "属性 " + strParamName + " 的值应当为数值型。出错信息: " + ex.Message;
                return -1;
            }

            return 0;
        }

        // 获得整数型的属性参数值
        // return:
        //      -1  出错。但是nValue中已经有了nDefaultValue值,可以不加警告而直接使用
        //      0   正常获得明确定义的参数值
        //      1   参数没有定义,因此代替以缺省参数值返回
        public static int GetIntegerParam(XmlNode node,
            string strParamName,
            long nDefaultValue,
            out long nValue,
            out string strError)
        {
            strError = "";
            nValue = nDefaultValue;

            string strValue = DomUtil.GetAttr(node, strParamName);

            if (String.IsNullOrEmpty(strValue) == true)
            {
                nValue = nDefaultValue;
                return 1;
            }

            try
            {
                nValue = Convert.ToInt64(strValue);
            }
            catch (Exception ex)
            {
                strError = "属性 " + strParamName + " 的值应当为数值型。出错信息: " + ex.Message;
                return -1;
            }

            return 0;
        }

        // 获得浮点数型的属性参数值
        // return:
        //      -1  出错。但是nValue中已经有了nDefaultValue值,可以不加警告而直接使用
        //      0   正常获得明确定义的参数值
        //      1   参数没有定义,因此代替以缺省参数值返回
        public static int GetDoubleParam(XmlNode node,
            string strParamName,
            double nDefaultValue,
            out double nValue,
            out string strError)
        {
            strError = "";
            nValue = nDefaultValue;

            string strValue = DomUtil.GetAttr(node, strParamName);

            if (String.IsNullOrEmpty(strValue) == true)
            {
                nValue = nDefaultValue;
                return 1;
            }

            try
            {
                nValue = Convert.ToDouble(strValue);
            }
            catch (Exception ex)
            {
                strError = "属性 " + strParamName + " 的值应当为(浮点)数值型。出错信息: " + ex.Message;
                return -1;
            }

            return 0;
        }

        // 包装后的版本
        // 不包含prolog
        public static int GetIndentXml(string strXml,
            out string strOutXml,
            out string strError)
        {
            return GetIndentXml(strXml,
                false,
                out strOutXml,
                out strError);
        }

        public static string GetIndentXml(string strXml)
        {
            string strOutXml = "";
            string strError = "";
            int nRet = GetIndentXml(strXml,
    false,
    out strOutXml,
    out strError);
            if (nRet == -1)
                return strError;
            return strOutXml;
        }

        // parameters:
        //      bHasProlog  是否prolog
        public static int GetIndentXml(string strXml,
            bool bHasProlog,
            out string strOutXml,
            out string strError)
        {
            strOutXml = "";
            strError = "";

            if (String.IsNullOrEmpty(strXml) == true)
            {
                return 0;
            }

            XmlDocument dom = new XmlDocument();
            try
            {
                dom.LoadXml(strXml);
            }
            catch (Exception ex)
            {
                strError = ex.Message;
                return -1;
            }

            if (bHasProlog == true)
                strOutXml = GetIndentXml(dom);
            else
                strOutXml = GetIndentXml(dom.DocumentElement);

            return 0;
        }

        // 获得缩进的XML源代码
        public static string GetIndentXml(XmlNode node)
        {
            using (MemoryStream m = new MemoryStream())
            using (XmlTextWriter w = new XmlTextWriter(m, Encoding.UTF8))
            {
                w.Formatting = Formatting.Indented;
                w.Indentation = 4;
                node.WriteTo(w);
                w.Flush();

                m.Seek(0, SeekOrigin.Begin);

                using (StreamReader sr = new StreamReader(m, Encoding.UTF8))
                {
                    string strText = sr.ReadToEnd();

                    //sr.Close();
                    //w.Close();

                    return strText;
                }
                // 注意,此后 m 已经关闭
            }
        }

        public static string GetIndentInnerXml(XmlNode node)
        {
            using (MemoryStream m = new MemoryStream())
            using (XmlTextWriter w = new XmlTextWriter(m, Encoding.UTF8))
            {
                w.Formatting = Formatting.Indented;
                w.Indentation = 4;
                node.WriteContentTo(w);
                w.Flush();

                m.Seek(0, SeekOrigin.Begin);

                using (StreamReader sr = new StreamReader(m, Encoding.UTF8))
                {
                    string strText = sr.ReadToEnd();
                    //sr.Close();
                    //w.Close();

                    return strText;
                }
                // 注意,此后 m 已经关闭
            }
        }

        public static string GetDomEncodingString(XmlDocument dom)
        {
            if (dom.FirstChild.NodeType == XmlNodeType.XmlDeclaration)
            {
                XmlDeclaration dec = (XmlDeclaration)dom.FirstChild;
                return dec.Encoding;
            }

            return null;
        }

        public static bool SetDomEncodingString(XmlDocument dom,
            string strEncoding)
        {
            if (dom.FirstChild.NodeType == XmlNodeType.XmlDeclaration)
            {
                XmlDeclaration dec = (XmlDeclaration)dom.FirstChild;
                dec.Encoding = strEncoding;
                return true;
            }

            return false;
        }

        // 获得缩进的XML源代码
        // 注:包含prolog等。如果不想包含这些,请用GetIndentXml(XmlNode)版本
        public static string GetIndentXml(XmlDocument dom)
        {
            string strEncoding = GetDomEncodingString(dom);
            Encoding encoding = Encoding.UTF8;
            if (string.IsNullOrEmpty(strEncoding) == false)
            {
                try
                {
                    encoding = Encoding.GetEncoding(strEncoding);
                }
                catch
                {
                    encoding = Encoding.UTF8;
                }
            }

            //
            using (MemoryStream m = new MemoryStream())
            using (XmlTextWriter w = new XmlTextWriter(m, encoding))
            {
                w.Formatting = Formatting.Indented;
                w.Indentation = 4;
                dom.Save(w);
                w.Flush();

                m.Seek(0, SeekOrigin.Begin);

                using (StreamReader sr = new StreamReader(m, encoding))
                {
                    string strText = sr.ReadToEnd();
                    //sr.Close();
                    //w.Close();

                    return strText;
                }
                // 注意,此后 m 已经关闭
            }
        }

        // 得到一个节点在父亲的儿子集中的序号 从0开始
        // parameters:
        //      node    儿子节点
        // return:
        //      返回在父亲的儿子集中的序号,-1没找到
        // 编写者: 任延华
        public static int GetIndex(XmlNode node)
        {
            Debug.Assert(node != null, "GetIndex()调用出错,node参数值不能为null。");

            XmlNode parentNode = node.ParentNode;
            for (int i = 0; i < parentNode.ChildNodes.Count; i++)
            {
                XmlNode curNode = parentNode.ChildNodes[i];
                if (curNode == node)
                    return i;
            }
            return -1;
        }

        // 得到parentNode的第一个element儿子节点
        // parameter:
        //		parentNode	父亲节点
        // return:
        //		第一个element儿子节点,未找到返回null
        // 编写者: 任延华
        public static XmlElement GetFirstElementChild(XmlNode parentNode)
        {
            Debug.Assert(parentNode != null, "GetFirstElementChild()出错,parentNode参数值不能为null。");

            for (int i = 0; i < parentNode.ChildNodes.Count; i++)
            {
                XmlNode node = parentNode.ChildNodes[i];
                if (node.NodeType == XmlNodeType.Element)
                    return (XmlElement)node;
            }
            return null;
        }

        // 得到parentNode的第一个CDATA儿子节点
        // parameter:
        //		parentNode	父亲节点
        // return:
        //		第一个XmlCDataSection儿子节点
        // 编写者: 任延华
        public static XmlCDataSection GetFirstCDATAChild(XmlNode parentNode)
        {
            Debug.Assert(parentNode != null, "GetFirstCDATAChild()出错,parentNode参数值不能为null。");

            for (int i = 0; i < parentNode.ChildNodes.Count; i++)
            {
                XmlNode node = parentNode.ChildNodes[i];
                if (node.NodeType == XmlNodeType.CDATA)
                    return (XmlCDataSection)node;
            }
            return null;
        }

        // 从根节点开始,根据指定的元素节点xpath和属性名,得到属性值
        // 编写者:谢涛
        public static string GetAttr(XmlNode nodeRoot,
            string strNodePath,
            string strAttrName)
        {
            XmlNode node = nodeRoot.SelectSingleNode(strNodePath);

            if (node == null)
                return "";

            return GetAttr(node, strAttrName);
        }

        // 探测XmlNode节点的指定属性是否存在
        // parameters:
        //      node        XmlNode节点
        //      strAttrName    属性名称
        // return:
        public static bool HasAttr(XmlNode node,
            string strAttrName)
        {
            Debug.Assert(node != null, "GetAttr()调用错误,node参数值不能为null。");
            Debug.Assert(strAttrName != null && strAttrName != "", "GetAttr()调用错误,strAttrName参数值不能为null或空字符串。");

            // 2012/4/25 NodeType == Document的节点,其Attributes成员为null
            if (node.Attributes == null)
                return false;

            if (node.Attributes[strAttrName] == null)
                return false;
            return true;
        }

        // 得到XmlNode节点的指定属性的值
        // TODO: 找属性使用的SelectSingleNode()函数,是否会浪费时间,可做测试与直接从node对应的属性集合中找属性用的时间比较。
        // parameters:
        //      node        XmlNode节点
        //      strAttrName    属性名称
        // return:
        //      返回属性值
        //      注:如何未找到指定的属性节点,返回""
        public static string GetAttr(XmlNode node,
            string strAttrName)
        {
            Debug.Assert(node != null, "GetAttr()调用错误,node参数值不能为null。");
            Debug.Assert(strAttrName != null && strAttrName != "", "GetAttr()调用错误,strAttrName参数值不能为null或空字符串。");

            // 2012/4/25 NodeType == Document的节点,其Attributes成员为null
            if (node.Attributes == null)
                return "";

            // 2012/2/16 优化
            XmlAttribute attr = node.Attributes[strAttrName];
            if (attr == null)
                return "";
            return attr.Value;
        }

        // 得到XmlNode节点指定名称空间的属性的值
        // parameters:
        //      strNameSpaceUrl 属性的名字空间的url
        //      node            XmlNode节点
        //      strAttrName        属性名称
        // return:
        //      指定属性的值
        //      注:如果未找到指定的属性节点,返回"";
        // ???找属性使用的SelectSingleNode()函数,是否会浪费时间,可做测试与直接从node对应的属性集合中找属性用的时间比较。
        public static string GetAttr(string strAttrNameSpaceUri,
            XmlNode node,
            string strAttrName)
        {
            Debug.Assert(node != null, "GetAttr()调用错误,node参数值不能为null。");
            Debug.Assert(strAttrName != null && strAttrName != "", "GetAttr()调用错误,strAttrName参数值不能为null或空字符串。");
            Debug.Assert(strAttrNameSpaceUri != null && strAttrNameSpaceUri != "",
                "GetAttr()调用错误,strNameSpaceUri参数值不能为null或空字符串。");

            XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
            nsmgr.AddNamespace("abc", strAttrNameSpaceUri);
            XmlNode nodeAttr = node.SelectSingleNode("@abc:" + strAttrName, nsmgr);

            if (nodeAttr == null)
                return "";
            else
                return nodeAttr.Value;
        }

        // 得到XmlNode节点的指定属性的值
        // parameters:
        //      node        XmlNode节点
        //      strAttrName    属性名称
        // return:
        //      返回属性值
        //      注:如何未找到指定的属性节点,返回null
        // 编写者:任延华
        // ???找属性使用的SelectSingleNode()函数,是否会浪费时间,可做测试与直接从node对应的属性集合中找属性用的时间比较。
        public static string GetAttrDiff(XmlNode node,
            string strAttrName)
        {
            Debug.Assert(node != null, "GetAttrDiff()调用错误,node参数值不能为null。");
            Debug.Assert(strAttrName != null && strAttrName != "", "GetAttrDiff()调用错误,strAttrName参数值不能为null或空字符串。");

            /*
            XmlNode nodeAttr = node.SelectSingleNode("@" + strAttrName);

            if (nodeAttr == null)
                return null;
            else
                return nodeAttr.Value;
             * */
            // 2012/4/25 NodeType == Document的节点,其Attributes成员为null
            if (node.Attributes == null)
                return null;

            // 2012/2/16 优化
            XmlAttribute attr = node.Attributes[strAttrName];
            if (attr == null)
                return null;
            return attr.Value;
        }

        // 编写者:谢涛
        public static string GetAttrOrDefault(XmlNode node,
            string strAttrName,
            string strDefault)
        {
            if (node == null)
                return strDefault;
            /*
            XmlNode nodeAttr = node.SelectSingleNode("@" + attrName);

            if (nodeAttr == null)
                return strDefault;
            else
                return nodeAttr.Value;
             * */

            Debug.Assert(node.Attributes != null, "");
            /*
            // 2012/4/25 NodeType == Document的节点,其Attributes成员为null
            if (node.Attributes == null)
                return strDefault;
             * */

            // 2012/2/16 优化
            XmlAttribute attr = node.Attributes[strAttrName];
            if (attr == null)
                return strDefault;
            return attr.Value;

        }

        // 设置XmlNode节点指定属性的值
        // 注: 2013/2/22 今后最好用 XmlElement node.SetAttribute(strAttrName, strAttrValue) 来替代本函数
        // parameters:
        //      node            XmlNode节点
        //      strAttrName     属性名称
        //      strAttrValue    属性值,可以为""或null,如果==null,表示删除这个属性
        public static void SetAttr(XmlNode node,
            string strAttrName,
            string strAttrValue)
        {
            Debug.Assert(node != null, "SetAttr()调用错误,node参数值不能为null。");
            Debug.Assert(strAttrName != null && strAttrName != "", "SetAttr()调用错误,strAttrName参数值不能为null或空字符串。");

            // 2012/4/25 NodeType == Document的节点,其Attributes成员为null
            Debug.Assert(node.Attributes != null, "");

            XmlAttributeCollection listAttr = node.Attributes;
            XmlAttribute attrFound = listAttr[strAttrName];

            if (attrFound == null)
            {
                if (strAttrValue == null)
                    return; // 本来就不存在

                XmlElement element = (XmlElement)node;
                element.SetAttribute(strAttrName, strAttrValue);
            }
            else
            {
                if (strAttrValue == null)
                    node.Attributes.Remove(attrFound);
                else
                    attrFound.Value = strAttrValue;
            }
        }

        // 设置XmlNode元素节点的属性值,名字空间版本
        // parameters:
        //      node                XmlNode节点
        //      strAttrName         属性名称
        //      strAttrNameSpaceURI 属性名字空间的URI
        //      strAttrValue        属性值,如果==null,则删除这个属性
        public static void SetAttr(XmlNode node,
            string strAttrName,
            string strAttrNameSpaceURI,
            string strAttrValue)
        {
            Debug.Assert(node != null, "SetAttr()调用错误,node参数值不能为null。");
            Debug.Assert(strAttrName != null && strAttrName != "", "SetAttr()调用错误,strAttrName参数值不能为null或空字符串。");
            Debug.Assert(strAttrNameSpaceURI != null && strAttrNameSpaceURI != "", "SetAttr()调用错误,strAttrNameSpaceURI参数值不能为null或空字符串。");

            // 2012/4/25 NodeType == Document的节点,其Attributes成员为null
            Debug.Assert(node.Attributes != null, "");

            XmlAttributeCollection listAttr = node.Attributes;
            XmlAttribute attrFound = listAttr[strAttrName, strAttrNameSpaceURI];

            if (attrFound == null)
            {
                if (strAttrValue == null)
                    return; // 本来就不存在

                XmlElement element = (XmlElement)node;
                element.SetAttribute(strAttrName, strAttrNameSpaceURI, strAttrValue);
            }
            else
            {
                if (strAttrValue == null)
                    node.Attributes.Remove(attrFound);
                else
                    attrFound.Value = strAttrValue;
            }
        }

        // 设置XmlNode元素节点的属性值,前缀和名字空间版本
        // parameters:
        //      node                XmlNode节点
        //      strAttrName         属性名称
        //      strPrefix   前缀
        //      strAttrNameSpaceURI 属性名字空间的URI
        //      strAttrValue        属性值,如果==null,则删除这个属性
        public static void SetAttr(XmlNode node,
            string strName,
            string strPrefix,
            string strNamespaceURI,
            string strValue)
        {
            Debug.Assert(node != null, "SetAttr()调用错误,node参数值不能为null。");
            Debug.Assert(String.IsNullOrEmpty(strName) == false, "SetAttr()调用错误,strName参数值不能为null或空字符串。");
            Debug.Assert(String.IsNullOrEmpty(strNamespaceURI) == false, "SetAttr()调用错误,strNamespaceURI参数值不能为null或空字符串。");
            Debug.Assert(String.IsNullOrEmpty(strPrefix) == false, "SetAttr()调用错误,strPrefix参数值不能为null或空字符串。");

            // 2012/4/25 NodeType == Document的节点,其Attributes成员为null
            Debug.Assert(node.Attributes != null, "");

            XmlAttribute attrFound = node.Attributes[strName, strNamespaceURI];

            if (attrFound == null)
            {
                if (strValue == null)
                    return; // 本来就不存在

                XmlElement element = (XmlElement)node;
                XmlAttribute attr = node.OwnerDocument.CreateAttribute(strPrefix, strName, strNamespaceURI);
                attr.Value = strValue;
                element.SetAttributeNode(attr);
            }
            else
            {
                if (strValue == null)
                    node.Attributes.Remove(attrFound);
                else
                    attrFound.Value = strValue;
            }
        }

        // 得到childNodes集合中,所有的CDATA节点
        // parameters:
        //      childNodes: 儿子节点集合,里面有各种类型的节点
        // return:
        //      返回所有CDATA节点组成的数组,如果一个CDATA节点都没有,返回一个空集合
        // 编写者:任延华
        public static ArrayList GetCdataNodes(XmlNodeList childNodes)
        {
            Debug.Assert(childNodes != null, "GetCdataNodes()调用错误,childNodes参数值不能为null。");

            ArrayList aCDATA = new ArrayList();
            foreach (XmlNode item in childNodes)
            {
                if (item.NodeType == XmlNodeType.CDATA)
                    aCDATA.Add(item);
            }
            return aCDATA;
        }

        // 通过strXpath路径逐级创建node,如果strXpath对应的节点已存在,则直接返回
        // paramter:
        //		nodeRoot	根节点
        //		strXpath	简单的xpath,最后一层可以是属性名称(即@属性名)
        // return:
        //      返回strXpath对应的节点
        // 编写者:任延华
        public static XmlNode CreateNodeByPath(XmlNode nodeRoot,
            string strXpath)
        {
            Debug.Assert(nodeRoot != null, "CreateNodeByPath()调用错误,nodeRoot参数值不能为null。");

            XmlNode nodeFound = nodeRoot.SelectSingleNode(strXpath);
            if (nodeFound != null)
                return nodeFound;

            string[] aNodeName = strXpath.Split(new Char[] { '/' });
            return DomUtil.CreateNode(nodeRoot, aNodeName);
        }

        // 根据名称数组逐级创建节点
        // parameters:
        //      nodeRoot    根节点
        //      aNodeName   节点名称数组
        // return:
        //      返回新创建的XmlNode节点
        // 编写者:任延华
        public static XmlNode CreateNode(XmlNode nodeRoot,
            string[] aNodeName)
        {
            XmlDocument dom = nodeRoot.OwnerDocument;
            if (dom == null)
            {
                if (nodeRoot is XmlDocument)
                    dom = (XmlDocument)nodeRoot;
                else
                    throw (new Exception("CreateNode()发生异常,nodeRoot的OwnerDocument属性值为null,且nodeRoot不是XmlDocument类型。"));
            }

            if (aNodeName.Length == 0)
                return null;

            int i = 0;
            if (aNodeName[0] == "")
                i = 1;

            XmlNode nodeCurrent = nodeRoot;
            XmlNode temp = null;
            for (; i < aNodeName.Length; i++)
            {
                string strOneName = aNodeName[i];
                if (strOneName == "")
                    throw new Exception("通过CreateNode()创建元素时,第'" + Convert.ToInt32(i) + "'级的名称为空。");

                temp = nodeCurrent.SelectSingleNode(strOneName);
                if (temp == null)
                {
                    Char firstChar = strOneName[0];
                    if (firstChar == '@' && i == aNodeName.Length - 1)
                    {
                        string strAttrName = strOneName.Substring(1);
                        if (strAttrName == "")
                            throw new Exception("通过CreateNode()创建元素时,第'" + Convert.ToInt32(i) + "'级的属性名称为空。");
                        DomUtil.SetAttr(nodeCurrent, strAttrName, "");
                        temp = nodeCurrent.SelectSingleNode("@" + strAttrName);
                        if (temp == null)
                            throw new Exception("已经创建了'" + strAttrName + "'属性,不可能找不到。");
                    }
                    else
                    {
                        temp = dom.CreateElement(aNodeName[i]);
                        nodeCurrent.AppendChild(temp);
                    }
                }
                nodeCurrent = temp;
            }

            return nodeCurrent;
        }

        // TODO: 逐渐废止这个函数
        // 得到node节点的第一个文本节点的值,相当于GetNodeFirstText()
        // parameter:
        //		node    XmlNode节点
        // result:
        //		node的第一个文本节点的字符串,不去空白
        //      注:如果node下级不存在文本节点,返回"";
        // 编写者:任延华
        public static string GetNodeText(XmlNode node)
        {
            Debug.Assert(node != null, "GetNodeText()调用出错,node参数值不能为null。");

            XmlNode nodeText = node.SelectSingleNode("text()");
            if (nodeText == null)
                return "";
            else
                return nodeText.Value;
        }

        // TODO: 逐渐废止这个函数
        // 得到node节点的第一个文本节点的值
        // parameter:
        //		node    XmlNode节点
        // result:
        //		node的第一个文本节点的字符串,左右去空白
        //      注:如果node下级不存在文本节点,返回null;
        // 编写者:任延华
        public static string GetNodeTextDiff(XmlNode node)
        {
            Debug.Assert(node != null, "GetNodeTextDiff()调用出错,node参数值不能为null。");

            XmlNode nodeText = node.SelectSingleNode("text()");
            if (nodeText == null)
                return null;
            else
                return nodeText.Value;
        }

        // 得到node节点的第一个文本节点的值
        // parameter:
        //		node    XmlNode节点
        // result:
        //		node的第一个文本节点的字符串,左右去空白
        //      注:如果node下级不存在文本节点,返回"";
        // 编写者:任延华
        public static string GetNodeFirstText(XmlNode node)
        {
            Debug.Assert(node != null, "GetNodeFirstText()调用出错,node参数值不能为null。");

            XmlNode nodeText = node.SelectSingleNode("text()");
            if (nodeText == null)
                return "";
            else
                return nodeText.Value.Trim();
        }

#if NO
        // TODO: 逐渐废止这个函数
        // 得到当前节点所有的文本节点值
		// parameter:
		//      node    XmlNode节点
		// result:
		//		node的所有文本节点组合起来的字符串,中间不加任何符号,去每个文字节点内容的左右空白
        //      注:如果node下级不存在文本节点,返回"";
		// 编写者:任延华
		public static string  GetNodeAllText(XmlNode node)
		{
            Debug.Assert(node != null, "GetNodeAllText()调用出错,node参数值不能为null。");

			XmlNodeList nodeTextList = node.SelectNodes("text()");
			string strResult = "";
			foreach(XmlNode oneNode in nodeTextList)
			{
				strResult += oneNode.Value.Trim ();   //把左右空白都去掉
			}
			return strResult;
		}
#endif

        // 设node节点的第一个文本节点的内容
        // parameters:
        //      node    XmlNode节点
        //      strNewText  新的文字内容
        // return:
        //      void
        // 编写者:任延华
        public static void SetNodeText(XmlNode node,
            string newText)
        {
            Debug.Assert(node != null, "SetNodeText()调用错误,node参数值不能为null。");

            XmlNode nodeText = node.SelectSingleNode("text()");
            if (nodeText == null)
                node.AppendChild(node.OwnerDocument.CreateTextNode(newText));
            else
                nodeText.Value = newText;
        }

        // 对指定的节点设第一个文本节点的值
        // 如果第一个文本节点存在,则直接给text赋值,
        // 如果第一个文本节点不存在,则调CreateNode()逐级创建节点,然后赋值
        // parameters:
        //      nodeRoot    根节点
        //      strXpath    节点路径
        //      strNewText  新文本值
        //      strError    out参数,返回出错信息
        // return:
        //      -1  出错
        //      0   成功
        // 编写者:任延华
        public static int SetNodeValue(XmlNode nodeRoot,
            string strXpath,
            string strNewText,
            out string strError)
        {
            strError = "";

            Debug.Assert(nodeRoot != null, "SetNodeValue()调用错误,nodeRoot参数值不能为null。");
            Debug.Assert(strXpath != null && strXpath != "", "SetNodeValue()调用错误,strXpath参数值不能为null或空字符串。");

            XmlNode nodeFound = nodeRoot.SelectSingleNode(strXpath);
            if (nodeFound == null)
            {
                string[] aNodeName = strXpath.Split(new Char[] { '/' });
                try
                {
                    nodeFound = DomUtil.CreateNode(nodeRoot, aNodeName);
                }
                catch (Exception ex)
                {
                    strError = "CreateNode()出错,原因:" + ex.Message;
                    return -1;
                }
            }

            if (nodeFound == null)
            {
                strError = "SetNodeValue(),此时nodeFound不可能为null了。";
                return -1;
            }

            DomUtil.SetNodeText(nodeFound, strNewText);
            return 0;
        }

        // TODO: 这个函数的功能令人费解,逐步废止?
        // 编写者: 谢涛
        public static int SetNodeValue(XmlNode nodeRoot,
            string strXpath,
            XmlNode newNode)
        {
            if (nodeRoot == null)
                return -1;

            XmlNode nodeFound = nodeRoot.SelectSingleNode(strXpath);

            if (nodeFound == null)
            {
                string[] aNodeName = strXpath.Split(new Char[] { '/' });
                nodeFound = CreateNode(nodeRoot, aNodeName);
            }

            if (nodeFound == null)
                return -1;

            //XmlNode nodeTemp = nodeFound.OwnerDocument.CreateElement("test");
            //nodeTemp = newNode.CloneNode(true);

            nodeFound.InnerXml = newNode.OuterXml;

            //nodeFound.AppendChild(newNode.CloneNode(true));

            return 0;
        }

        // 2006/11/29
        public static string GetElementInnerXml(XmlNode nodeRoot,
    string strXpath)
        {
            XmlNode node = nodeRoot.SelectSingleNode(strXpath);
            if (node == null)
                return "";

            return node.InnerXml;
        }

        // 写入一个元素文本
        // return:
        //      返回该元素的XmlNode
        public static XmlNode SetElementInnerXml(XmlNode nodeRoot,
            string strXpath,
            string strInnerXml)
        {
            if (nodeRoot == null)
            {
                throw (new Exception("nodeRoot参数不能为null"));
            }

            XmlNode nodeFound = nodeRoot.SelectSingleNode(strXpath);

            if (nodeFound == null)
            {
                string[] aNodeName = strXpath.Split(new Char[] { '/' });
                nodeFound = CreateNode(nodeRoot, aNodeName);
            }

            if (nodeFound == null)
            {
                throw (new Exception("SetElementInnerXml() CreateNode error"));
            }

            nodeFound.InnerXml = strInnerXml;
            return nodeFound;
        }

        // 2006/11/29
        public static string GetElementOuterXml(XmlNode nodeRoot,
    string strXpath)
        {
            XmlNode node = nodeRoot.SelectSingleNode(strXpath);
            if (node == null)
                return "";

            return node.OuterXml;
        }

        public static bool IsEmptyElement(XmlNode nodeRoot,
    string strXpath)
        {
            XmlNode node = nodeRoot.SelectSingleNode(strXpath);
            if (node == null)
                return true;

            if (node.Attributes.Count == 0 && node.ChildNodes.Count == 0)
                return true;

            return false;
        }

        // 写入一个元素文本
        // return:
        //      返回该元素的XmlNode
        public static XmlNode SetElementOuterXml(XmlNode nodeRoot,
            string strXpath,
            string strOuterXml)
        {
            if (nodeRoot == null)
                throw new ArgumentException("nodeRoot 参数值不应为空", "nodeRoot");

            XmlNode nodeFound = nodeRoot.SelectSingleNode(strXpath);
            if (nodeFound == null)
            {
                string[] aNodeName = strXpath.Split(new Char[] { '/' });
                nodeFound = CreateNode(nodeRoot, aNodeName);
            }

            if (nodeFound == null)
            {
                throw (new Exception("SetElementOuterXml() CreateNode error"));
            }

            if (string.IsNullOrEmpty(strOuterXml) == false)
            {
                XmlDocumentFragment fragment = nodeFound.OwnerDocument.CreateDocumentFragment();
                fragment.InnerXml = strOuterXml;

                nodeFound.ParentNode.InsertAfter(fragment, nodeFound);

                nodeFound.ParentNode.RemoveChild(nodeFound);

                nodeFound = nodeRoot.SelectSingleNode(strXpath);
                return nodeFound;
            }
            else
            {
                // 2016/11/5
                nodeFound.ParentNode.RemoveChild(nodeFound);
                return null;
            }
        }

        // 2009/10/31
        // 2016/11/3 允许 strOuterXml 为空。这时候的效果是删除 node 元素
        // 写入一个元素的 OuterXml
        // exception:
        //      可能会因为 strOuterXml 格式不正确而抛出异常
        // return:
        //      返回变动后该元素的 XmlNode
        public static XmlElement SetElementOuterXml(XmlElement element,
            string strOuterXml)
        {
            if (element == null)
            {
                throw new ArgumentException("node 参数值不应为空", "node");
            }

            XmlElement new_element = null;
            if (string.IsNullOrEmpty(strOuterXml) == false)
            {
                XmlDocumentFragment fragment = element.OwnerDocument.CreateDocumentFragment();
                fragment.InnerXml = strOuterXml;

                element.ParentNode.InsertAfter(fragment, element);

                // 2020/6/9 注意 NextSibling 可能是非 XmlElement 类型的节点
                XmlNode current = element;
                while (current.NextSibling != null)
                {
                    if (current.NextSibling is XmlElement)
                    {
                        new_element = current.NextSibling as XmlElement;    // 2012/12/12 新增加
                        break;
                    }
                    current = current.NextSibling;
                }
            }
            element.ParentNode.RemoveChild(element);
            return new_element;
        }

        // 插入新对象到儿子们的最前面
        public static XmlNode InsertFirstChild(XmlNode parent, XmlNode newChild)
        {
            XmlNode refChild = null;
            if (parent.ChildNodes.Count > 0)
                refChild = parent.ChildNodes[0];

            return parent.InsertBefore(newChild, refChild);
        }

        // 2012/9/30
        public static string GetElementInnerText(XmlNode nodeRoot,
    string strXpath)
        {
            XmlNode node = nodeRoot.SelectSingleNode(strXpath);
            if (node == null)
                return null;

            return node.InnerText.Trim();
        }

        // 2012/9/30
        // 获得一个元素的一个属性值
        public static string GetElementAttr(XmlNode nodeRoot,
            string strXpath,
            string strAttrName)
        {
            XmlNode node = nodeRoot.SelectSingleNode(strXpath);
            if (node == null)
                return null;
            XmlAttribute attr = node.Attributes[strAttrName];
            if (attr == null)
                return null;
            return attr.Value.Trim();
        }

        // 编写者: 谢涛
        public static string GetElementText(XmlNode nodeRoot,
            string strXpath)
        {
            XmlNode node = nodeRoot.SelectSingleNode(strXpath);
            if (node == null)
                return "";

            XmlNode nodeText;
            nodeText = node.SelectSingleNode("text()");

            if (nodeText == null)
                return "";
            else
                return nodeText.Value;
        }

        // 新版本 2006/10/24
        // 获得一个元素的下级文本
        // 一并返回元素节点对象
        public static string GetElementText(XmlNode nodeRoot,
            string strXpath,
            out XmlNode node)
        {
            node = nodeRoot.SelectSingleNode(strXpath);
            if (node == null)
                return "";

            return node.InnerText;
        }

        // 编写者: 谢涛
        public static string GetElementText(XmlNode nodeRoot,
            string strXpath,
            XmlNamespaceManager mngr)
        {
            XmlNode node = nodeRoot.SelectSingleNode(strXpath, mngr);
            if (node == null)
                return "";

            XmlNode nodeText;
            nodeText = node.SelectSingleNode("text()");

            if (nodeText == null)
                return "";
            else
                return nodeText.Value;
        }

        // 删除一个元素 2006/10/26
        // return:
        //      返回被删除掉的XmlNode
        public static XmlNode DeleteElement(XmlNode nodeRoot,
            string strXpath)
        {
            if (nodeRoot == null)
            {
                throw (new Exception("nodeRoot参数不能为null"));
            }

            XmlNode nodeFound = nodeRoot.SelectSingleNode(strXpath);

            if (nodeFound == null)
                return null;    // 既然不存在,正好也不必删除了

            return nodeFound.ParentNode.RemoveChild(nodeFound);
        }

        // 删除若干个元素 2011/1/11
        // return:
        //      返回被删除掉的XmlNode数组
        public static List<XmlNode> DeleteElements(XmlNode nodeRoot,
            string strXpath)
        {
            if (nodeRoot == null)
            {
                throw (new Exception("nodeRoot参数不能为null"));
            }

            XmlNodeList nodes = nodeRoot.SelectNodes(strXpath);

            if (nodes.Count == 0)
                return null;    // 既然不存在,正好也不必删除了

            List<XmlNode> deleted_nodes = new List<XmlNode>();
            foreach (XmlNode node in nodes)
            {
                if (node.ParentNode == null)
                    continue;
                deleted_nodes.Add(node.ParentNode.RemoveChild(node));
            }

            return deleted_nodes;
        }

        /*
        // 移除一个元素
        // 2007/6/19
        public static XmlNode RemoveElement(XmlNode nodeRoot,
            string strXPath)
        {
            if (nodeRoot == null)
            {
                throw (new Exception("nodeRoot参数不能为null"));
            }

            XmlNode nodeFound = nodeRoot.SelectSingleNode(strXPath);

            if (nodeFound == null)
            {
                // 正好不存在,也不必删除了
                return null;
            }

            nodeFound.ParentNode.RemoveChild(nodeFound);

            return nodeFound;
        }*/

        // 替换全部控制字符
        // parameters:
        //      chReplace   要替换成的字符。如果为 0 ,表示删除控制字符
        static string ReplaceControlChars(string strText,
            char chReplace)
        {
            if (String.IsNullOrEmpty(strText) == true)
                return strText;

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < strText.Length; i++)
            {
                char ch = strText[i];
                if (ch >= 0x1 && ch <= 0x1f)
                {
                    if (chReplace != 0)
                        sb.Append(chReplace);
                }
                else
                    sb.Append(ch);
            }

            return sb.ToString();
        }

        // 替换控制字符,但不替换 \0d \0a
        // parameters:
        //      chReplace   要替换成的字符。如果为 0 ,表示删除控制字符
        public static string ReplaceControlCharsButCrLf(string strText,
    char chReplace)
        {
            if (String.IsNullOrEmpty(strText) == true)
                return strText;

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < strText.Length; i++)
            {
                char ch = strText[i];
                if (ch >= 0x1 && ch <= 0x1f && ch != 0x0d && ch != 0x0a)
                {
                    if (chReplace != 0)
                        sb.Append(chReplace);
                }
                else
                    sb.Append(ch);
            }

            return sb.ToString();
        }

        // 2010/21/16
        // 写入一个元素文本
        // 不去替换ControlChars
        // return:
        //      返回该元素的XmlNode
        public static XmlNode SetElementTextPure(XmlNode nodeRoot,
            string strXpath,
            string strText)
        {
            if (nodeRoot == null)
            {
                throw (new Exception("nodeRoot参数不能为null"));
            }

            XmlNode nodeFound = nodeRoot.SelectSingleNode(strXpath);

            /*
            // 2007/6/19
            if (nodeFound == null && strText == null)
            {
                // 正好不存在,也不必删除了
                return null;
            }*/

            if (nodeFound == null)
            {
                string[] aNodeName = strXpath.Split(new Char[] { '/' });
                nodeFound = CreateNode(nodeRoot, aNodeName);
            }

            if (nodeFound == null)
            {
                throw (new Exception("SetElementText() CreateNode error"));
            }

            if (String.IsNullOrEmpty(strText) == true)
                nodeFound.InnerText = strText;
            else
                nodeFound.InnerText = strText;

            return nodeFound;
        }

        // 2022/3/16
        // 对 strText 不替换里面的控制字符
        public static XmlElement SetElementTextEx(XmlElement nodeRoot,
    string strXpath,
    string strText)
        {
            if (nodeRoot == null)
            {
                throw (new ArgumentException("nodeRoot参数不能为null"));
            }

            XmlElement nodeFound = nodeRoot.SelectSingleNode(strXpath) as XmlElement;

            if (nodeFound == null)
            {
                string[] aNodeName = strXpath.Split(new Char[] { '/' });
                nodeFound = CreateNode(nodeRoot, aNodeName) as XmlElement;
            }

            if (nodeFound == null)
            {
                throw (new Exception("SetElementText() CreateNode error"));
            }

            if (String.IsNullOrEmpty(strText) == true)
                nodeFound.InnerText = strText;
            else
                nodeFound.InnerText = strText;  // 不替换

            return nodeFound;
        }

        // 2019/8/4 返回类型从 XmlNode 修改为 XmlElement
        // 写入一个元素文本
        // 文本内容中可以包含回车换行符号,但其他控制字符在写入的时候会被过滤为星号
        // return:
        //      返回该元素的XmlNode
        public static XmlElement SetElementText(XmlNode nodeRoot,
            string strXpath,
            string strText)
        {
            if (nodeRoot == null)
            {
                throw (new Exception("nodeRoot参数不能为null"));
            }

            XmlElement nodeFound = nodeRoot.SelectSingleNode(strXpath) as XmlElement;

            /*
            // 2007/6/19
            if (nodeFound == null && strText == null)
            {
                // 正好不存在,也不必删除了
                return null;
            }*/

            if (nodeFound == null)
            {
                string[] aNodeName = strXpath.Split(new Char[] { '/' });
                nodeFound = CreateNode(nodeRoot, aNodeName) as XmlElement;
            }

            if (nodeFound == null)
            {
                throw (new Exception("SetElementText() CreateNode error"));
            }

            /*
            if (strText == null)
            {
                // 2007/6/19
                nodeFound.ParentNode.RemoveChild(nodeFound);
            }
            else
             * */

            if (String.IsNullOrEmpty(strText) == true)
                nodeFound.InnerText = strText;
            else
                nodeFound.InnerText = ReplaceControlCharsButCrLf(strText, '*'); // 2013/3/12 ReplaceControlCharsButCrLf()   // 2008/12/19 ReplaceControlChars()

            return nodeFound;
        }

        // 得到node节点相对于nodeRoot节点的xpath路径
        // parameters:
        //      nodeRoot    根节点
        //      node        指定的节点
        //      strXpath    out参数,返回node相对于nodeRoot的xpath路径
        //      strError    out参数,返回出错信息
        // return:
        //      -1  出错,当node不属于nodeRoot下级时
        //      0   成功
        // 编写者: 任延华
        public static int Node2Path(XmlNode nodeRoot,
            XmlNode node,
            out string strXpath,
            out string strError)
        {
            strXpath = "";
            strError = "";

            Debug.Assert(nodeRoot != null, "Node2Path()调用错误,nodeRoot参数值不能为null。");
            Debug.Assert(node != null, "Node2Path()调用错误,node参数值不能为null。");

            //当node为属性节点时,加了属性xpath字符串
            string strAttr = "";
            if (node.NodeType == XmlNodeType.Attribute)
            {
                strAttr = "/@" + node.Name;
                XmlAttribute AttrNode = (XmlAttribute)node;
                node = AttrNode.OwnerElement;
            }

            bool bBelongRoot = false;

            while (node != null)
            {
                if (node == nodeRoot)
                {
                    bBelongRoot = true;
                    break;
                }

                XmlNode nodeMyself = node;

                node = node.ParentNode;
                if (node == null)
                    break;

                XmlNode nodeTemp = node.FirstChild;
                int nIndex = 1;
                while (nodeTemp != null)
                {
                    if (nodeTemp == nodeMyself) //Equals(nodeTemp,nodeMyself))
                    {
                        if (strXpath != "")
                            strXpath = "/" + strXpath;

                        strXpath = nodeMyself.Name + "[" + System.Convert.ToString(nIndex) + "]" + strXpath;
                        break;
                    }
                    if (nodeTemp.Name == nodeMyself.Name)
                        nIndex += 1;

                    nodeTemp = nodeTemp.NextSibling;
                }
            }

            if (bBelongRoot == false)
            {
                strError = "Node2Path()调用错误,node不属于nodeRoot的下级";
                return -1;
            }

            strXpath = strXpath + strAttr;
            return 0;
        }

    } // DomUtil类结束

}


text:
Critical Insights: Mary Shelley
Editor: Virginia Brackett
Tags: 1 Volume300 PagesEssays Offering Analysis by Top Literary ScholarsIntroductory Essay by the EditorChronology of Author's LifeComplete List of Author's WorksDetailed Bio of the EditorGeneral BibliographyGeneral Subject IndexPublication Dates of Works
A great starting point for students seeking an introduction to Mary Shelley and the critical discussions surrounding her work.
Best known as the author of the ubiquitous Gothic novel, Frankenstein; or, The Modern Prometheus, Mary Shelley lived an eventful, though grief-stricken life, between troubled finances, her father's disownment, and the death of multiple children. Topics discussed in this compilation include autobiographical elements and themes in her work, the influence of Frankenstein today, and her relationship with her husband, Romantic poet-philosopher Percy Bysshe Shelley. A writer whose biographical details historically attracted as much attention as her art, Shelley has garnered an enthusiastic twenty-first century critical reception for her expanded collection of work, which includes six novels and one novella, dozens of short stories, essays, poetry, travel pieces, and children's literature.
This volume embraces both, celebrating the traditional approach to reading Shelley, while also introducing young readers to more recent interests surrounding her writing. Each essay complements the others, relating through a rich offering of theory and illustration. The result is a tapestry of readings that will interest any reader, whatever her level of previous knowledge about Shelley's work. Essay topics include disability studies, women's education, critical reception and cultural context, trauma, criminal justice in Frankenstein, and gender and form in her short fiction.
Each Critical Insights Edition is divided into four sections: An Introduction, Critical Contexts, Critical Readings, and Resources. In Critical Contexts, the provided essays aim to provide a background to the title, author, or theme that is historical, cultural, and biographical foundation for the reader. The essays in Critical Readings utilize common critcal approaches to further analyze the author's work, or specific works according to the selected theme. Each essay is 2,500 to 5,000 words in length, and all essays conclude with a list of "Works Cited," along with endnotes. Finally, the volume's appendixes offer a section of useful reference resources:
A chronology of the author's life
A complete list of the author's works and their original dates of publication
A general bibliography
A detailed paragraph on the volume's editor
Notes on the individual chapter authors
A subject index
" "Critical Insights: Mary Shelley is an excellent source for teachers, professors, students, and scholars of nineteenth-century English writers. Highly recommended."
Critical Insights: Mary Shelley Review
Critical Insights: Technology & Humanity
Great starting point for students seeking an introduction to the theme and the critical discussions surrounding it.
Critical Insights: The American Thriller
An exploration of the authors and literary works that identify with the American thriller, this volume examines the prominent themes and stories of the genre.
Critical Insights: Southern Gothic Literature
Outstanding, in-depth scholarship by renowned literary critics; great starting point for students seeking an introduction to the theme and the critical discussions surrounding it.

redpajama_set_name: RedPajamaCommonCrawl


text:
using System.Collections.Generic;

namespace Tup.Cobar4Net.Parser.Ast.Expression.Primary.Function.String
{
    /// <author>
    ///     QIU Shuo
    /// </author>
    public class SubstringIndex : FunctionExpression
    {
        public SubstringIndex(IList<IExpression> arguments)
            : base("SUBSTRING_INDEX", arguments)
        {
        }

        public override FunctionExpression ConstructFunction(IList<IExpression> arguments)
        {
            return new SubstringIndex(arguments);
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
Titanic (THX / DTS-ES 6.1) "Special Collector's Edition"
Thread starter Robin
Title: Titanic (THX / DTS-ES 6.1) "Special Collector's Edition"
Film Studio: Paramount / 20th Century Fox / Lightstorm Entertainment
This film won the best picture and best director 'Oscars' and a total of 11 'Oscars' in 1997. Not that's why I enjoy it so much..., I would have liked this picture no matter what... It has all of the elements I look for in a film, an interesting / compelling story, captivating / creative screen play and dialog, great acting with chemistry, wonderful direction, fantastic and trilling set design, cinematography and special effects - which really move me, that's pretty much all I need from a film. Titanic more than meets my expectations.
Kate Winslet, is absolutely stunning in her role, for Titanic... She is passionate and beautiful. Forget the fact, she is one of my all time favorite actresses, she has real chemistry with not only Leonardo Dicaprio, but everyone she (her character) is positively involved with in the film, from the 'Designer of Titanic' to the 'Third Class' people she comes into contact with. Winslet is the remarkable spark in this production... Leonardo Dicaprio was very good in his performance. He has chemistry and was more than adequate opposite Winslet. I thought, Billy Zane played a great despot, you just love to hate. Whereas, Bill Paxton's played his character wonderfully, as an interesting modern day explorer / treasure hunter in search of the 'Heart of the Ocean', a fabulously huge diamond.
James Cameron's direction was wonderful, technically creative and inspired for Titanic. Where Titanic differs from, and moves far beyond Cameron's previous films, Titanic is much more of a human story. Cameron wrote this story as a much more dramatic story with interactions and intricacies far beyond his other films. It may sound funny now, but I think Cameron did take a huge professional risk with Titanic. Fortunately, and to his credit and it paid off in a big way - successfully as we all know... James Cameron, having mastered the technically challenging special effects genre of films like; "The Terminator", "T2" and "Aliens". I could tell, he was heading for a film like Titanic, especially after he did the "Abyss" and "True Lies", he was just looking for the proper subject to write about... James Cameron, for the most part, always writes and directs his films, and Titanic is no exception. It's like writing the film, helps him to actually, make the film... Cameron, always totally immerses himself in his film projects, spending sixteen to eighteen hours a day on a film, from the beginning to completion of the production. It is his perfectionism and dedication, to his creative vision which is a hallmark of his excellent films. It all paid off with Titanic...
A word about this latest edition of Titanic, on DVD... Firstly, Titanic has never looked or sounded better, presented in, 'THX / DTS-ES 6.1', which is the current maximum, state-of-the-DVD-art (pre Blue-Ray anyway). Secondly, there are three DVD disc's in this 'Special Collector's Edition' box set. To fit all of the extra THX / DTS-ES 6.1, bites of disc information of this, 194 minute film, and the addition of pertinent, though excellent featurettes, on disc's 1 and 2 - required splitting the feature film up into two DVD disc's (which always reminds me of the old 'Laser Disc' format, of having to switch the disc's during the movie). The third DVD disc, is exclusively a bonus features disc, which includes 45 minutes of Never-Before-Seen Deleted Scenes - completely lovingly restored to film feature quality(sight and sound),and a host of other fantastic DVD featurettes on the making of this great classic film.
I thoroughly enjoyed Titanic on DVD. My Martin Logan, HT was singing from beginning to the end. I loved all of the bonus material and special featurettes in this marvelous DVD set.
I highly recommend Titanic, as a great American film classic, and one of James Cameron's best works to date. I only wish he would get back into the 'Writing / Directing' business again, with another great film. The good thing is, I hear he is working on another project as we speak, currently entitled: "Battle Angle". You can read all about it on this web link:
http://http://us.imdb.com/title/tt0437086/
HT relaxed, comfortably surrounded in ML bliss, until next time, let the movies turn you on...
-Robin
B000ANVQ0K.01._SCLZZZZZZZ_.jpg


Even Super Bowl winners need a coach! How about you?
Our elite team of consultants can aid you with a wide variety of specialist services.
Accepted training to meet both NRCan (CGSB) and ASNT minimum theory training standards.Our online training courses also meet: SNT, AWS, NAS-410, CP-105, and ISO 9712 Theory-Training specifications or recommended practices.


Still, at least their version of Android won;t be susceptible to all those dodgy patent lawsuits. Well, it will, but they won't give a sh1t. Actually, a bit like Google really.
You're reporting this like they've developed a whole new web browser of their own ... take a closer look - IT'S CHROME - Based on the chromium code most likely, with a little customisation on top to make it 'theirs'.
You should really be reporting this as "Baidu created a chrome clone using the open source chrome code base! SHOCK HORROR!"
"Baidu Browser uses IE for web browsing and Webkit for applications"
It looks like Chrome but uses Trident in addition to Webkit.
"Baidu also has aspirations outside its Chinese roots, where it will have to fight Google on a level playing field."
How does a Chinese knockoff compete with something that's already free?
How could they compete? One word - tanks!
Yes Asia is king at apeing stuff. Might have something to do with their schools that teach that creativity is dangerous and evil. They still need the west to invent the stuff they then mass produce. As I say what makes the USA safe no matter which way the winds blow is Hollywood. Even the Chinese want their Brad Pitt fix.
Hmm, let's weight that up for a moment.
... every other good and service known to man, plus Brad Pitt (on a knockoff DVD). Plus interest on the loans currently keeping USA Inc. afloat.
It is the education system and the watchful eye of the Chinese Govt that screws with innovation and creativity. Namely, everything is done by rote (the workings of Confucious - still taught in the system - actually promotes this), and even if one becomes a creator and inventor outside the system, the authorities monitor your success and worm their way in. Don't like it? Become an automaton.
It is for this precise reason that countries like America and Britain can easily take talented (potentially and realised) Chinese from the country to use for their own companies i.e. use the expertise of highly skilled Chinese for their own advantage, whilst simultaneously depriving China of those skills. A bit sad really.
As for the browser itself, I don't get this fascination the Chinese have with IE. Surely they know that it is easily hacked, thus allowing their computers to become bots? Or maybe that's their plan, feign ignorance through the instability of IE.


We are at the tail end of the first-quarter earnings season. The current reporting cycle is on track to record the strongest growth in the past seven years. Total earnings are expected to be up 23.6% on revenue growth of 8.8%, per the latest Earnings Outlook report. This is much higher than 13.4% earnings growth and 8.1% revenue growth recorded in Q4.
The bullish projection for the quarter have been attributed to factors like the corporate tax overhaul apart from an improving economy and a much-improved job market.
Per the report, 444 S&P 500 members have reported quarterly results. While 77.7% of these companies delivered positive earnings surprise, 75% beat top-line expectations. Earnings of these companies increased 24.5% from the year-ago quarter, while revenues rose 9.3%.
Given the prevalent healthy scenario, all the 16 Zacks sectors are projected to end the current reporting cycle with year-over-year earnings growth. Moreover, 13 are anticipated to display double-digit earnings growth.
S&P 500 members from the Business Services sector have already reported financial numbers and recorded top- and bottom-line growth of 22.5% and 6.8%, respectively in the first quarter of 2018.
The sector benefited from a strong U.S. economy, reduced tax rates, robust manufacturing and non-manufacturing activities, easing of the U.S. dollar and momentum in oil prices.
Gross Domestic Product (GDP) grew at a seasonally adjusted annual rate of 2.3% in the first quarter of 2018, following 2.6% gain in the fourth quarter of 2018, per the "advance" estimate released by the Bureau of Economic Analysis.
The slowdown in growth was mainly due to seasonal quirk and economists expect growth to accelerate in the second quarter. Lower corporate and individual tax rates along with increased government spending are expected to push annual economic growth to the 3% target.
Economic activity in the manufacturing sector expanded in April and the overall economy grew for the 108th consecutive month. U.S. manufacturing activity continued its robust performance in April as the PMI measured by ISM touched 57.3%. This shows strong growth in manufacturing for the 20th consecutive month, driven by continued increase in new orders, production activity and employment and inventories. Of the 18 manufacturing industries, 17 reported growth in April.
The employment index grew 54.2% in April, which indicates employment growth for the 19th consecutive month. Of the 18 manufacturing industries, 12 reported employment growth. The increase came as companies are hiring more skilled workers and indirect personnel.
As far as the non-manufacturing sector is concerned, NMI was 56.8% in April, recording the 99th consecutive month of expansion. While the Prices Index gained 0.3% to 61.8%, Employment Index declined 3% to 536%. As many as 18 non-manufacturing industries reported growth.
Continuous increase in PMI, NMI and the number of jobs offered by manufacturing giants further boost optimism.
Given the bullish sentiment surrounding business services stocks, it will not be a bad idea to add companies that have the potential to report better-than-expected earnings this time around.
However, given the high degree of diversity in the sector, picking the right stocks for your portfolio might appear to be a colossal task. An easy way to narrow down the list is by choosing stocks that have a favorable Zacks Rank #1 (Strong Buy) or 2 (Buy) or 3 (Hold) and a positive Earnings ESP. This can be done with the help of the Zacks Stock Screener.
Earnings ESP is our proprietary methodology for determining the stocks that have the best chances to surprise with their next earnings announcement. Earnings ESP shows the percentage difference between the Most Accurate estimate and the Zacks Consensus Estimate. You can uncover the best stocks to buy or sell before they're reported with our Earnings ESP Filter.
Our research shows that for stocks with this combination, the chance of a positive earnings surprise is as high as 70%. Here are four business services stocks that match the abovementioned criteria and thus may emerge winners in this reporting cycle.
News and information provider Thomson Reuters Corp (NYSE:TRI) currently carries a Zacks Rank #2 and has an Earnings ESP of +7.36%. The company's earnings surpassed the Zacks Consensus Estimate in all the previous four quarters, delivering an average positive earnings surprise of 14.3%.
Moreover, in the last 60 days, the Zacks Consensus Estimate for first-quarter 2018 earnings increased 11.5% to 58 cents per share. Full-year earnings estimates increased 7% to $2.28 per share in the same time frame. The company is slated to report quarterly results before the bell on May 11.
In the last 60 days, the Zacks Consensus Estimate for first-quarter 2018 earnings increased 2.3% to 45 cents per share. Full-year earnings estimates increased 0.5% to $1.94 per share in the same time frame. The company is slated to report quarterly results on May 29 before market opens.
Integrated financial information and analytical applications provider, FactSet Research Systems Inc. (NYSE:FDS) has an Earnings ESP of +0.23% and Zacks Rank #3 (Hold). The company's earnings surpassed the Zacks Consensus Estimate in the last four quarters, with an average beat of 1.9%.
The Zacks Consensus Estimate for third-quarter fiscal 2018 earnings increased 1.4% to $2.14 per share. Full-year earnings estimates increased 1.3% to $8.48 per share in the same time frame. The company is expected to report quarterly results on Jun 26.
Payroll, human resource, retirement, and insurance services provider, Paychex, Inc. (NASDAQ:PAYX) surpassed the Zacks Consensus Estimate in each of the last four quarters, with an average beat of 1.7%. It has a Zacks Rank #3 and an Earnings ESP of +9.28%.
Over the last 60 days, the Zacks Consensus Estimate for third-quarter fiscal 2018 earnings remained unchanged at 61 cents per share. Full-year earnings estimates increased 1.6% to $2.49 per share in the same time frame. The company is expected to report quarterly results on Jun 27.
Article printed from InvestorPlace Media, https://investorplace.com/2018/05/4-business-services-stocks-poised-beat-earnings-estimates-ggsyn/.


Basic Problems in Dating a Sugar Daddy and how to Solve Them?
Why You Should Join Paid Sugar Daddy Websites To Looking For Sugar Daddy?
How To Be a Good Sugar Baby?
Online Dating (PC OR APP)?
How To Treat Your Sugar Baby or Sugar Daddy Correctly?
Relationship is more of a commitment. There are other things that need to be considered especially when dating a rich sugar daddy or sugar baby. Not all relationship is the same ..
At present sugar baby - sugar daddy dating has become extremely popular wherein a beautiful girl is looking forward to seeking arrangements for cash from an affluent man and in return they provide these men with their companionship..
Why Sugar Daddy Sites are the Best Valentine's Day present for Ambitious Singles?
Nowadays, sugar daddies dating sites are the best places for ladies to hook up with their favorite sugar daddies. Compared to young men, there are many benefits ladies get from them. That is why nowadays, most single ladies..
How to Find a Sugar Daddy/Sugar Mama?
Sugar daddy or sugar mama is an older male or female who can get a mind of any monetary concern you might meet for attractive.It is important that sugar babies are not prostitutes. It is precisely why they aren't accessible from the street.As an obvious actuality, .
Why Rich Sugar Daddies Like To Join The Online Dating Site?
Have you noticed the current increase in the number of sugar daddies in the online dating sites? Online dating sites have become a place of solace for many older and rich sugar daddies in the world today. It is worrying how widely these sugar daddy dating sites are being used. ..
In the world of dating, there are so many different tastes for every occasion. Some people are attracted to little fuller figures. Others prefer rail thin persons. Some love honesty while others love muscles. Still others prefer stability in all core areas more than anything else..
Why Seeking Arrangements Sugar Daddy Website is Popular?
SeekingArrangements.org is one of the most popular sugar daddy websites. It works on the principle of creating a platform where sugar daddies or mommies and sugar babies can meet and build a mutually beneficial relationship..
What kind of men should be a sugar daddy?


Did you know that solar panels were once installed on the White House roof? Then they were removed. Then put back again?
The White House itself harvests the power of the sun. Solar photovoltaic panels and water heaters are installed on the building's roof.
It all started back in 1979 when then-President Jimmy Carter installed 32 solar panels on the White House roof.
The panels were used to heat water for the first family and for water in the White House laundry and cafeteria.
But he was wrong. The White House did not have solar panels in 2000.
To understand what happened, we have to go back to the Reagan administration.
The 32 panels were ripped out in 1986, as, "Yes," you guessed right. The Reagan administration weren't fans of solar.
Some people argue that the solar panels weren't actually ripped out. That they were removed because of required work on the roof beneath them, and not due to spite or anti-environmentalism.
Scientific American reported that by 1986, the Reagan administration had gutted the research and development budgets for renewable energy at the then-fledgling U.S. Department of Energy (DoE) and eliminated tax breaks for the deployment of wind turbines and solar technologies—recommitting the nation to reliance on cheap but polluting fossil fuels, often from foreign suppliers.
Carter's panels were rudimentary, but it's estimated they generated 12,264 kWh of energy per year.
That's more than the average amount of energy an American home uses annually or the equivalent of 9,197 pounds of burning coal.
Solar panels didn't return to the White House grounds until 2002.
The Bush administration installed solar water heaters on the Cabana's roof to heat the White House pool.
Solar photovoltaic panels were also installed on the White House roof in 2014.
They are 6 times more powerful than the previous ones and will pay for themselves after 8 years of use.
The Trump administration just has to keep them there, but with Trump's roll-backs on every progressive policy on climate change mitigation and renewable energy incentives including those developed by the Obama administration, who knows?
Also for some reason, Carter's solar panels can be seen today at museums and show houses all over the world.
One resides at the Smithsonian's National Museum of American History, one at the Carter Library and, one joined the collection of the Solar Science and Technology Museum in Dezhou, China.
Huang Ming, chairman of Himin Solar Energy Group Co., the largest manufacturer of such solar hot water heaters in the world, accepted the donation for permanent display there.
After all, companies like his in China now produce some 80 percent of the solar water heaters used in the world today.
Great history lesson, it appears that republican administrations have continuously held back renewable energy technology. America would have been the leader in solar had not Regan' and the Bush administrations denial campaigns succeeded. Now we have the most brazen climate denier POTUS. We the people elected them so we the people will suffer from our choices.


A loving household supplies the muse youngsters need to succeed, and robust households with a person and a lady – bonded together for life – at all times have been, and all the time might be, the key to such households.
An important factor a father can do for his children is to love their mother. Your children love you as a result of there may be never a uninteresting second with you around. Granting the order in Parramatta Native Court, Magistrate Margaret McGlynn stated that it can be crucial the public be made conscious of conditions of this sort wherein these kids unfortunately discovered themselves.. children whose start parents being siblings and plenty of of their relations being of incestuous relationships of some variety".


text:
SOMOLU LG CHAIRMAN 'DULLAR' APPLAUD RESIDENTS ON RELIGIOUS TOLERANCE …Says Hard-Work And Loyalty Pays
1stEleven9jaTv August 18, 2021 3 min read
Residents of Somolu Local Government Area were applauded for the religious tolerance among themselves, creating avenue to be their neighbours' keeper in an area known to playing host to people of various ethnic groups.
The Executive Chairman of Somolu Local Government, Hon. Abdul Hamed Salawu applauded the residents earlier yesterday during the special prayer session hosted by his immediate official staff members and political aides.
At the thanksgiving prayer session held at the Conference Hall of the council secretariat, members of the management team of the council were there to join in the prayerful celebration of the return of the workaholic Chairman who is well known for given free food to the elderly people in his area.
In his sermon, Sheikh AbdulHakeem Akorede Hissa admonished the Council Chairman to always remain thankful to Allah as it's not everyone who desire good deeds are able to do it. He said the leadership style of Hon. Abdul Hamed Salawu in ensuring his followers are well taken care of is a way of building more leaders for a better tomorrow. The Nasrul-Lahi-L-Fatih clergyman urged the council helmsman to forget the pain of the past but should remain with the lessons. He however, charged the Chairman's aides on loyalty, truthfulness and steadfastness.
Meanwhile, Pastor Stephen Oladiran of Christ Apostolic Faith, on his part, preached about love and unity as the secret that will make Hon. Abdul Hamed Salawu achieve more than what he has achieved during his first term in office. He emphasised that wisdom is an important spiritual tool that every leader needs to enjoy and expand their followers. He prayed that God will bless the Council Chairman with more wisdom greater than that of King Solomon.
Meeting with the clergymen in his office, Hon. Abdul Hamed Salawu said Somolu is a peaceful and that can't be unrelated to the fact that Muslims, Christians and Traditionalists are living as one family. "We are our neighbours keepers and we can't have a programme in the council here without ensuring all religions are represented".
However, he assured his aides that hard-work is not an hidden attribute but can be easily seen. He charged them to put in their best to serve the government and the people of Somolu with total loyalty. "When you put in your best in this government with total loyalty, you will smile always because it pays", Dullar said.
Deacon Femi Taiwo (APC Chairman, Somolu), Alhaji Hammond Jinadu, Mr. Yusuf Salawu (Chairman's brother), Hon. Afolarin Olubiyi (Chief of Staff), Hon. Ayodele Afolabi (SA, Special Duties), Hon. Lekan Otaiku (SA, Political Matters) including the Chairman's Personal Assistant, Mr. Adetola Orekoya and Chief Press Secretary, Oseni Owolabi 'Ajimomuya'.
The civil servants working with Hon. Abdul Hamed Salawu were not left out as Mrs. Ruth Taiwo (Confidential Secretary), Mrs. Oluremi Adedayo (Administrative P.A.), Mrs. Seyi Benson (Front desk Officer), Mrs. Toyin (Clerk), including security personnel and service supporting staff members with the SSA New Media 1, Oladapo Jegede, took part in the prayer session.
Owolabi Oseni 'Ajimomuya'
Chief Press Secretary,
Somolu Local Government.
Shocking! Popular Evangelist's Husband Commits Suicide In Ondo
His Imperial Majesty (HIM) Ọba Adéyeyè Enitan Ògúnwùsì (Òjájá II), Ọọ̀ni'rìsà of Ilé-Ifẹ delighteth us With His Imperial Visit – Rev Esther Abimbola Ajayi


20 ways to draw is perfect for illustrators cartoonists doodlers and anyone who loves to sketch. I really love sketch and as an early adopter have been using it since v2 was released. Best of all its free.
It has the best apparatus to hit the background cut off the photos or images and make additional changes to fulfill all of your stretchy needs.
Sketch jason mask drawing. Beautifully illustrated these inspirational sketchbooks will help you learn how to draw anything. I am from urban north london but now live in urbane davis california. Alexandria ocasio cortez dance video goes viral pelosi vows different world for trump in new congress. Draw a chibi boy drawing tutorial will teach you step by step draw a chibi boy in no time.
20 ways to draw series a sketchbook for artists designers and doodlers let your imagination shine. Maas 1 new york times and usa today bestselling author of the throne of glass series 6 out now the court of thorns and roses series 4 out may 3rd 2018. Even if the mask helmet or head itself isnt very expressive you can still get a lot of mileage out of disembodied eyebrowsfor other emotion conveying clothing see expressive shirtif a character has a similarly animated skull for a head then it is an expressive skull. The main issue for me is the little bugs and inconsistencies that have me often questioning if its something ive done wrong or if its a bug with the app.
Urban sketchers show the world one drawing at a time. I sketch i write sometimes do things and go places and my name is pete. Choosing the right one saving time. Usa today politics blog.
We are greatly committed to provide the most outstanding services in clipping path photo masking photo retouching color correction raster to vector conversion clipping mask.


This fabulous sun protection hat by Puffin Gear® has it all! UPF 50+ sun protection rating makes it a must for outdoor play. A chin tie with cord lock and breakaway clip keeps hat safely secure. Hats are preshrunk and machine washable. Join the dinosaur party.


Funny thing, KHR just coincidentally found this: https://archive.org/details/msdos_Stunts_1990 You just need to have the list of "security system" codes.
O hey, looks like I'm a little behind the times.
Great! I wonder if the online games are slower than "native" ones.
I think they just place an entire emulator in your temporary internet files and run the game from there. So there shouldn't be that much of a difference.
You could try Ctrl+F12 a few times to up the simulation speed? Or were you already comparing them in that modus?
EDIT: Related to this, I noticed Dosbox is available for Android these days. Does anyone have any experience with that? Could Stunts on a phone work?
I think it might reset every now and then, because the record is again 1'36"


Artisan Nail Studio is a colorful + creative space located in the historic Fourth Ward district in Charlotte, NC. We are committed to providing our clients with a quality nail care experience each time. We are confident in our craft and strive to exceed your expectations. From gel polish manicures to intricate nail artistry, we look forward to servicing your nail care needs.


This exercise practises scanning -- that means reading very fast to find specific pieces of information. You have a very short time to scan the text and locate answers to the questions.
Every second, one hectare of the world's rainforest is destroyed. That's equivalent to two football fields. An area the size of New York City is lost every day. In a year, that adds up to 31 million hectares -- more than the land area of Poland. This alarming rate of destruction has serious consequences for the environment; scientists estimate, for example, that 137 species of plant, insect or animal become extinct every day due to logging. In British Columbia, where, since 1990, thirteen rainforest valleys have been clearcut, 142 species of salmon have already become extinct, and the habitats of grizzly bears, wolves and many other creatures are threatened. Logging, however, provides jobs, profits, taxes for the govenment and cheap products of all kinds for consumers, so the government is reluctant to restrict or control it.
Much of Canada's forestry production goes towards making pulp and paper. According to the Canadian Pulp and Paper Association, Canada supplies 34% of the world's wood pulp and 49% of its newsprint paper. If these paper products could be produced in some other way, Canadian forests could be preserved. Recently, a possible alternative way of producing paper has been suggested by agriculturalists and environmentalists: a plant called hemp.
Hemp has been cultivated by many cultures for thousands of years. It produces fibre which can be made into paper, fuel, oils, textiles, food, and rope. For centuries, it was essential to the economies of many countries because it was used to make the ropes and cables used on sailing ships; colonial expansion and the establishment of a world-wide trading network would not have been feasible without hemp. Nowadays, ships' cables are usually made from wire or synthetic fibres, but scientists are now suggesting that the cultivation of hemp should be revived for the production of paper and pulp. According to its proponents, four times as much paper can be produced from land using hemp rather than trees, and many environmentalists believe that the large-scale cultivation of hemp could reduce the pressure on Canada's forests.
However, there is a problem: hemp is illegal in many countries of the world. This plant, so useful for fibre, rope, oil, fuel and textiles, is a species of cannabis, related to the plant from which marijuana is produced. In the late 1930s, a movement to ban the drug marijuana began to gather force, resulting in the eventual banning of the cultivation not only of the plant used to produce the drug, but also of the commercial fibre-producing hemp plant. Although both George Washington and Thomas Jefferson grew hemp in large quantities on their own land, any American growing the plant today would soon find himself in prison -- despite the fact that marijuana cannot be produced from the hemp plant, since it contains almost no THC (the active ingredient in the drug).
In recent years, two major movements for legalization have been gathering strength. One group of activists believes that ALL cannabis should be legal -- both the hemp plant and the marijuana plant -- and that the use of the drug marijuana should not be an offense. They argue that marijuana is not dangerous or addictive, and that it is used by large numbers of people who are not criminals but productive members of society. They also point out that marijuana is less toxic than alcohol or tobacco. The other legalization movement is concerned only with the hemp plant used to produce fibre; this group wants to make it legal to cultivate the plant and sell the fibre for paper and pulp production. This second group has had a major triumph recently: in 1997, Canada legalized the farming of hemp for fibre. For the first time since 1938, hundreds of farmers are planting this crop, and soon we can expect to see pulp and paper produced from this new source.
How many species of salmon have become extinct in BC?
How much of the world's newsprint paper is supplied by Canada?
What equipment on a ship was made from hemp?
What drug can be obtained from a relative of hemp?
Where was hemp farming recently legalized?