Exemplo n.º 1
0
        // 返回一段元素
        public MarcNodeList getAt(int start, int length)
        {
            MarcNodeList results = new MarcNodeList();

            if (length == 0)
            {
                return(results);
            }

            if (start < 0 || start >= this.count)
            {
                throw new Exception("index值 " + start.ToString() + " 超出许可范围");
            }
            if (start + length - 1 < 0 || start + length - 1 >= this.count)
            {
                throw new Exception("index + length 值 " + (start + length).ToString() + " 超出许可范围");
            }

            for (int i = 0; i < length; i++)
            {
                results.add(this[start + i]);
            }

            return(results);
        }
Exemplo n.º 2
0
        // 返回某些元素
        // parameters:
        //      length  要取得的个数。如果为-1,表示从index一直取到末尾
        /// <summary>
        /// 获得当前集合中一段范围的元素
        /// </summary>
        /// <param name="index">起点下标</param>
        /// <param name="length">个数</param>
        /// <returns>指定的元素(所构成的一个新集合)</returns>
        public MarcNodeList getAt(int index, int length)
        {
            MarcNodeList results = new MarcNodeList();

            if (length == 0)
            {
                return(results);
            }
            if (index < 0 || index >= this.count)
            {
                throw new ArgumentException("index值 " + index.ToString() + " 超出许可范围", "index");
            }

            if (length == -1)
            {
                length = this.count - index;
            }

            if (index + length < 0 || index + length - 1 >= this.count)
            {
                throw new ArgumentException("index+length值 " + (index + length).ToString() + " 超出许可范围");
            }

            for (int i = index; i < index + length; i++)
            {
                results.add(this[i]);
            }

            return(results);
        }
Exemplo n.º 3
0
        // 对一批互相没有树重叠关系的对象进行筛选
        static MarcNodeList simpleSelect(MarcNodeList source,
                                         string strXPath,
                                         int nMaxCount = -1)
        {
            // 准备一个模拟的记录节点
            // MarcRecord record = new MarcRecord();
            MarcNode temp_root = new MarcNode();

            temp_root.Name = "temp";

            // 保存下集合中所有的Parent指针
            List <MarcNode> parents = new List <MarcNode>();

            foreach (MarcNode node in source)
            {
                // 保存指针
                parents.Add(node.Parent);

                // 建立父子关系,但原来位置的ChidNodes并不摘除
                temp_root.ChildNodes.baseAdd(node);
                node.Parent = temp_root;
                // Debug.Assert(node.Parent == temp_root, "");
            }
            Debug.Assert(parents.Count == source.count, "");

            try
            {
                MarcNodeList results = new MarcNodeList();

                MarcNavigator nav = new MarcNavigator(temp_root);  // 出发点在模拟的记录节点上

                XPathNodeIterator ni = nav.Select(strXPath);
                while (ni.MoveNext() && (nMaxCount == -1 || results.count < nMaxCount))
                {
                    NaviItem item = ((MarcNavigator)ni.Current).Item;
                    if (item.Type != NaviItemType.Element)
                    {
                        throw new Exception("xpath '" + strXPath + "' 命中了非元素类型的节点,这是不允许的");
                        continue;
                    }
                    if (results.indexOf(item.MarcNode) == -1)   // 不重复的才加入
                    {
                        results.add(item.MarcNode);
                    }
                }
                return(results);
            }
            finally
            {
                // 恢复原先的 Parent 指针
                Debug.Assert(parents.Count == source.count, "");
                for (int i = 0; i < source.count; i++)
                {
                    source[i].Parent = parents[i];
                }
            }
        }
Exemplo n.º 4
0
        // 针对集合中的元素进行 XPath 筛选
        // 本函数不怕同一批元素之间有重叠关系。所采用的策略是一批一批单独筛选,然后把输出结果合成
        // parameters:
        //      nMaxCount    至多选择开头这么多个元素。-1表示不限制
        /// <summary>
        /// 针对当前集合中的全部元素进行 XPath 选择
        /// </summary>
        /// <param name="strXPath">XPath字符串</param>
        /// <param name="nMaxCount">限制命中的最大元素个数。如果为 -1,表示不限制</param>
        /// <returns>选中的元素所构成的新集合</returns>
        public MarcNodeList select(string strXPath, int nMaxCount /* = -1*/)
        {
            // 把当前集合分割为每段内部确保互相不重叠
            List <MarcNodeList> lists = new List <MarcNodeList>();

            {
                MarcNodeList segment = new MarcNodeList();  // 当前累积的段落
                foreach (MarcNode node in this)
                {
                    if (segment.count > 0)
                    {
                        if (isCross(node, segment) == true)
                        {
                            // 推走
                            lists.Add(segment);
                            segment = new MarcNodeList();
                        }
                    }
                    segment.add(node);
                }

                // 最后剩下的
                if (segment.count > 0)
                {
                    lists.Add(segment);
                }
            }


            MarcNodeList results = new MarcNodeList();

            foreach (MarcNodeList segment in lists)
            {
                // 对一批互相没有树重叠关系的对象进行筛选
                MarcNodeList temp = simpleSelect(segment,
                                                 strXPath,
                                                 -1);
                foreach (MarcNode node in temp)
                {
                    if (results.indexOf(node) == -1)
                    {
                        results.add(node);
                    }
                }

                if (nMaxCount != -1 && results.count >= nMaxCount)
                {
                    if (results.count > nMaxCount)
                    {
                        return(results.getAt(0, nMaxCount));
                    }
                    break;
                }
            }
            return(results);
        }
Exemplo n.º 5
0
        // 返回最后一个元素
        /// <summary>
        /// 获得当前集合的最后一个元素
        /// </summary>
        /// <returns>当前集合的最后一个元素(所构成的一个新集合)</returns>
        public MarcNodeList last()
        {
            MarcNodeList results = new MarcNodeList();

            if (this.count > 0)
            {
                results.add(this[this.count - 1]);
            }

            return(results);
        }
Exemplo n.º 6
0
        // 复制出一个新的集合
        // 注意,不但数组(框架)被复制,其中每个元素都重新复制
        /// <summary>
        /// 根据当前集合复制出一个新的集合对象。本方法采取的是否深度复制策略,即新集合中的每个元素都是复制品
        /// </summary>
        /// <returns>新的集合</returns>
        public MarcNodeList clone()
        {
            MarcNodeList result = new MarcNodeList();

            foreach (MarcNode node in this)
            {
                result.add(node.clone());
            }

            return(result);
        }
Exemplo n.º 7
0
        // 返回某个元素
        /// <summary>
        /// 获得指定下标位置的元素
        /// </summary>
        /// <param name="index">下标</param>
        /// <returns>指定的元素(所构成的一个新集合)</returns>
        public MarcNodeList getAt(int index)
        {
            MarcNodeList results = new MarcNodeList();

            if (index < 0 || index >= this.count)
            {
                throw new ArgumentException("index值 " + index.ToString() + " 超出许可范围", "index");
            }

            results.add(this[index]);

            return(results);
        }
Exemplo n.º 8
0
        // 从数组中移走全部对象
        // 注意,本函数并不修改所移走的对象的Parent成员。也就是说移走的对象并未完全被detach
        // 返回移出的nodes
        /// <summary>
        /// 从当前集合中移走全部元素。注意,本函数并不修改所移走的元素的 Parent 成员。也就是说移走的元素并未完全被摘除
        /// </summary>
        /// <returns>已经被移走的全部元素</returns>
        public MarcNodeList remove()
        {
            MarcNodeList results = new MarcNodeList();

            for (int i = 0; i < this.count; i++)
            {
                MarcNode node = this[i];
                MarcNode temp = node.remove();
                if (temp != null)
                {
                    results.add(node);
                }
            }

            return(results);
        }
Exemplo n.º 9
0
        // 在目标集合中每个元素的DOM位置后面(同级)插入源集合内的元素
        // 注1: 如果目标集合为空,则本函数不作任何操作。这样可以防止元素被摘除但没有插入到任何位置
        // 注2:将 源 插入到 目标 元素的DOM位置后面。如果源头元素在DOM树上,则先摘除它然后插入到新位置,不是复制。
        // 注3: 如果目标集合中包含多于一个元素,则分为多轮插入。第二轮以后插入的对象,是源集合中的对象复制出来的新对象
        /// <summary>
        /// 在目标集合中每个元素的 DOM 位置后面(同级)插入源集合内的元素
        /// </summary>
        /// <param name="source_nodes">源集合</param>
        /// <param name="target_nodes">目标集合</param>
        public static void insertAfter(
            MarcNodeList source_nodes,
            MarcNodeList target_nodes)
        {
            if (source_nodes.count == 0)
            {
                return;
            }
            if (target_nodes.count == 0)
            {
                return;
            }

            // record.SelectNodes("field[@name='690']")[0].ChildNodes.after(SUBFLD + "x第一个" + SUBFLD + "z第二个");
            if (target_nodes is ChildNodeList)
            {
                // 数组框架复制,但其中的元素不是复制而是引用
                MarcNodeList temp = new MarcNodeList();
                temp.add(target_nodes);
                target_nodes = temp;
            }

            // 先(从原有DOM位置)摘除当前集合内的全部元素
            source_nodes.detach();
            int i = 0;

            foreach (MarcNode target_node in target_nodes)
            {
                MarcNode target = target_node;
                foreach (MarcNode source_node in source_nodes)
                {
                    MarcNode source = source_node;
                    if (i > 0)  // 第一轮以后,源对象每个都要复制后插入目标位置
                    {
                        source = source.clone();
                        target.after(source);
                    }
                    else
                    {
                        target.after(source);
                    }
                    target = source;   // 插入后参考位置要顺延
                }
                i++;
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// 在目标集合中每个元素的 DOM 位置前面(同级)插入源集合内的元素
        /// </summary>
        /// <param name="source_nodes">源集合</param>
        /// <param name="target_nodes">目标集合</param>
        public static void insertBefore(
            MarcNodeList source_nodes,
            MarcNodeList target_nodes)
        {
            if (source_nodes.count == 0)
            {
                return;
            }
            if (target_nodes.count == 0)
            {
                return;
            }

            if (target_nodes is ChildNodeList)
            {
                // 数组框架复制,但其中的元素不是复制而是引用
                MarcNodeList temp = new MarcNodeList();
                temp.add(target_nodes);
                target_nodes = temp;
            }

            // 先(从原有DOM位置)摘除当前集合内的全部元素
            source_nodes.detach();
            int i = 0;

            foreach (MarcNode target_node in target_nodes)
            {
                MarcNode target = target_node;
                foreach (MarcNode source_node in source_nodes)
                {
                    MarcNode source = source_node;
                    if (i > 0)  // 第一轮以后,源对象每个都要复制后插入目标位置
                    {
                        source = source.clone();
                        target.before(source);
                    }
                    else
                    {
                        target.before(source);
                    }
                    target = source;   // 插入后参考位置要顺延
                }
                i++;
            }
        }
Exemplo n.º 11
0
        // 在目标集合中每个元素的DOM位置 下级开头 插入源集合内的元素
        /// <summary>
        /// 在目标集合中每个元素的 DOM 位置下级开头插入源集合内的元素
        /// </summary>
        /// <param name="source_nodes">源集合</param>
        /// <param name="target_nodes">目标集合</param>
        public static void prepend(
            MarcNodeList source_nodes,
            MarcNodeList target_nodes)
        {
            if (source_nodes.count == 0)
            {
                return;
            }
            if (target_nodes.count == 0)
            {
                return;
            }

            // 防范目标集合被动态修改后发生foreach报错
            if (target_nodes is ChildNodeList)
            {
                // 数组框架复制,但其中的元素不是复制而是引用
                MarcNodeList temp = new MarcNodeList();
                temp.add(target_nodes);
                target_nodes = temp;
            }

            // 先(从原有DOM位置)摘除当前集合内的全部元素
            source_nodes.detach();
            int i = 0;

            foreach (MarcNode target_node in target_nodes)
            {
                foreach (MarcNode source_node in source_nodes)
                {
                    MarcNode source = source_node;
                    if (i > 0)  // 第一轮以后,源对象每个都要复制后插入目标位置
                    {
                        source = source.clone();
                        target_node.prepend(source);
                    }
                    else
                    {
                        target_node.prepend(source);
                    }
                }
                i++;
            }
        }
Exemplo n.º 12
0
        // 针对DOM树进行 XPath 筛选
        // parameters:
        //      nMaxCount    至多选择开头这么多个元素。-1表示不限制
        /// <summary>
        /// 用 XPath 字符串选择节点
        /// </summary>
        /// <param name="strXPath">XPath 字符串</param>
        /// <param name="nMaxCount">限制命中的最多节点数。-1表示不限制</param>
        /// <returns>被选中的节点集合</returns>
        public MarcNodeList select(string strXPath, int nMaxCount /* = -1*/)
        {
            MarcNodeList results = new MarcNodeList();

            MarcNavigator nav = new MarcNavigator(this);  // 出发点在当前对象

            XPathNodeIterator ni = nav.Select(strXPath);

            while (ni.MoveNext() && (nMaxCount == -1 || results.count < nMaxCount))
            {
                NaviItem item = ((MarcNavigator)ni.Current).Item;
                if (item.Type != NaviItemType.Element)
                {
                    // if (bSkipNoneElement == false)
                    throw new Exception("xpath '" + strXPath + "' 命中了非元素类型的节点,这是不允许的");
                    continue;
                }
                results.add(item.MarcNode);
            }
            return(results);
        }
Exemplo n.º 13
0
        /// <summary>
        /// 根据机内格式 MARC 字符串,创建若干 MarcInnerField 对象
        /// </summary>
        /// <param name="strText">MARC 机内格式字符串。代表内嵌字段的那个局部。例如 "$1200  $axxxx$fxxxx$1225  $axxxx"</param>
        /// <param name="strLeadingString">返回引导字符串。也就是第一个子字段符号前的部分</param>
        /// <returns>新创建的 MarcInnerField 对象数组</returns>
        public static MarcNodeList createInnerFields(
            string strText,
            out string strLeadingString)
        {
            strLeadingString = "";
            MarcNodeList results = new MarcNodeList();

            strText = strText.Replace(SUBFLD + "1", FLDEND);

            List <string> segments = new List <string>();
            StringBuilder prefix   = new StringBuilder(); // 第一个 30 出现以前的一段文字
            StringBuilder segment  = new StringBuilder(); // 正在追加的内容段落

            for (int i = 0; i < strText.Length; i++)
            {
                char ch = strText[i];
                if (ch == FLDEND[0])
                {
                    // 如果先前有累积的,推走
                    if (segment.Length > 0)
                    {
                        segments.Add(segment.ToString());
                        segment.Clear();
                    }

                    //segment.Append(ch);
                    segment.Append(SUBFLD + "1");
                }
                else
                {
                    if (segment.Length > 0 || segments.Count > 0)
                    {
                        segment.Append(ch);
                    }
                    else
                    {
                        prefix.Append(ch);// 第一个子字段符号以前的内容放在这里
                    }
                }
            }

            if (segment.Length > 0)
            {
                segments.Add(segment.ToString());
                segment.Clear();
            }

            if (prefix.Length > 0)
            {
                strLeadingString = prefix.ToString();
            }


            foreach (string s in segments)
            {
                string strSegment = s;

                MarcInnerField field = null;
                field = new MarcInnerField();

                // 如果长度不足 5 字符,补齐
                // 5 字符是 $1200 的意思
                if (strSegment.Length < 5)
                {
                    strSegment = strSegment.PadRight(5, '?');
                }

                field.Text = strSegment;
                results.add(field);
                // Debug.Assert(field.Parent == parent, "");
            }

            return(results);
        }
Exemplo n.º 14
0
        // 根据机内格式的片断字符串,构造若干MarcSubfield对象
        // parameters:
        //      parent      要赋给新创建的MarcSubfield对象的Parent值
        //      strLeadingString   [out] 第一个 31 字符以前的文本部分
        /// <summary>
        /// 根据机内格式 MARC 字符串,创建若干 MarcSubfield 对象
        /// </summary>
        /// <param name="strText">MARC 机内格式字符串</param>
        /// <param name="strLeadingString">返回前导部分字符串。也就是 strText 中第一个子字段符号以前的部分</param>
        /// <returns>新创建的 MarcSubfield 对象集合</returns>
        public static MarcNodeList createSubfields(
            string strText,
            out string strLeadingString)
        {
            strLeadingString = "";
            MarcNodeList results = new MarcNodeList();

            List <string> segments = new List <string>();
            StringBuilder prefix   = new StringBuilder(); // 第一个 31 出现以前的一段文字
            StringBuilder segment  = new StringBuilder(); // 正在追加的内容段落

            for (int i = 0; i < strText.Length; i++)
            {
                char ch = strText[i];
                if (ch == 31)
                {
                    // 如果先前有累积的,推走
                    if (segment.Length > 0)
                    {
                        segments.Add(segment.ToString());
                        segment.Clear();
                    }

                    segment.Append(ch);
                }
                else
                {
                    if (segment.Length > 0 || segments.Count > 0)
                    {
                        segment.Append(ch);
                    }
                    else
                    {
                        prefix.Append(ch);// 第一个子字段符号以前的内容放在这里
                    }
                }
            }

            if (segment.Length > 0)
            {
                segments.Add(segment.ToString());
                segment.Clear();
            }

            if (prefix.Length > 0)
            {
                strLeadingString = prefix.ToString();
            }

            foreach (string s in segments)
            {
                MarcSubfield subfield = new MarcSubfield();
                if (s.Length < 2)
                {
                    subfield.Text = MarcQuery.SUBFLD + "?";  // TODO: 或者可以忽略?
                }
                else
                {
                    subfield.Text = s;
                }
                results.add(subfield);
                // Debug.Assert(subfield.Parent == parent, "");
            }

            return(results);
        }
Exemplo n.º 15
0
        /// <summary>
        /// 根据机内格式 MARC 字符串,创建若干 MarcField (或 MarcOuterField) 对象
        /// </summary>
        /// <param name="strText">MARC 机内格式字符串</param>
        /// <param name="strOuterFieldDef">嵌套字段的定义。缺省为 null,表示不使用嵌套字段。这是一个列举字段名的逗号间隔的列表('*'为通配符),或者 '@' 字符后面携带一个正则表达式</param>
        /// <returns>新创建的 MarcField 对象集合</returns>
        public static MarcNodeList createFields(
            string strText,
            string strOuterFieldDef = null)
        {
            MarcNodeList results = new MarcNodeList();

            List <string> segments   = new List <string>();
            StringBuilder field_text = new StringBuilder(4096);

            for (int i = 0; i < strText.Length; i++)
            {
                char ch = strText[i];
                if (ch == 30 || ch == 29)
                {
                    // 上一个字段结束
                    segments.Add(field_text.ToString());
                    field_text.Clear();
                }
                else
                {
                    field_text.Append(ch);
                }
            }

            // 剩余的内容
            if (field_text.Length > 0)
            {
                segments.Add(field_text.ToString());
                field_text.Clear();
            }

            foreach (string segment in segments)
            {
                string strSegment = segment;

                // 如果长度不足 3 字符,补齐?
                if (strSegment.Length < 3)
                {
                    strSegment = strSegment.PadRight(3, '?');
                }

                // 创建头标区以后的普通字段
                MarcNode field = null;
                if (string.IsNullOrEmpty(strOuterFieldDef) == false)
                {
                    string strFieldName = strSegment.Substring(0, 3);
                    // return:
                    //		-1	error
                    //		0	not match
                    //		1	match
                    int nRet = MatchName(strFieldName,
                                         strOuterFieldDef);
                    if (nRet == 1)
                    {
                        field = new MarcOuterField();
                    }
                    else
                    {
                        field = new MarcField();
                    }
                }
                else
                {
                    field = new MarcField();
                }


                field.Text = strSegment;
                results.add(field);
                // Debug.Assert(field.Parent == parent, "");
            }

            return(results);
        }