// 从指定位置移走一个对象 // 返回包含移走的对象的集合 /// <summary> /// 从指定下标位置移走一个元素 /// </summary> /// <param name="index">要移走对象的下标</param> /// <returns>被移走的一个元素(所构成的新集合)</returns> public MarcNodeList removeAt(int index) { MarcNodeList results = new MarcNodeList(this.m_list[index]); this.m_list.RemoveAt(index); return(results); }
// 把strText构造的新对象插入到this的下级开头位置。返回this /// <summary> /// 用指定的字符串构造出新节点,插入到当前节点的子节点开头 /// </summary> /// <param name="strText">用于构造新节点的字符串</param> /// <returns>当前节点</returns> public MarcNode prepend(string strText) { MarcNodeList targets = new MarcNodeList(this); targets.prepend(strText); return(this); }
// 返回一段元素 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); }
// 返回某些元素 // 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); }
/// <summary> /// 将 USMARC 记录从 880 模式转换为 平行模式 /// </summary> /// <param name="record">要处理的记录</param> public static void ToParallel(MarcRecord record) { // 选定全部 880 字段 MarcNodeList fields = record.select("field[@name='880']"); if (fields.count == 0) { return; } foreach (MarcField field in fields) { string content_6 = field.select("subfield[@name='6']").FirstContent; if (string.IsNullOrEmpty(content_6) == true) { continue; } // 拆解 $6 内容 string strFieldName = ""; string strNumber = ""; string strScriptId = ""; string strOrientation = ""; _parseSubfield6(content_6, out strFieldName, out strNumber, out strScriptId, out strOrientation); if (string.IsNullOrEmpty(strScriptId) == true) { // 修正 $6 // 例子 ISBN 9789860139976 strScriptId = "$1"; field.select("subfield[@name='6']").Content = _buildSubfield6(strFieldName, strNumber, strScriptId, strOrientation); } // 找到关联的字段 MarcField main_field = _findField(record, strFieldName, field.Name, strNumber); if (main_field != null) { // 创建一个新的字段,把 880 字段内容复制过去 MarcField new_field = new MarcField(strFieldName, field.Indicator, field.Content); // 新字段插入到关联字段后面 main_field.after(new_field); // 删除 880 字段 field.detach(); main_field.select("subfield[@name='6']").Content = _buildSubfield6(strFieldName, strNumber, "", ""); } else { // 找不到关联的字段,把 880 字段的字段名修改了即可 field.Name = strFieldName; } } }
// 把strText构造的新对象插入到this的后面。返回this /// <summary> /// 用指定的字符串构造出新的节点,插入到当前节点的后面兄弟位置 /// </summary> /// <param name="strText">用于构造新节点的字符串</param> /// <returns>当前节点</returns> public MarcNode after(string strText) { MarcNodeList targets = new MarcNodeList(this); targets.after(strText); return(this); }
// 追加 /// <summary> /// 在当前集合末尾追加若干节点元素 /// </summary> /// <param name="list">要追加的若干节点元素</param> public new void add(MarcNodeList list) { base.add(list); Debug.Assert(owner != null, ""); foreach (MarcNode node in list) { node.Parent = owner; } }
// 对一批互相没有树重叠关系的对象进行筛选 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]; } } }
// 针对集合中的元素进行 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); }
// 追加若干元素 // 返回增补对象后的当前集合 /// <summary> /// 在当前集合末尾添加若干元素 /// </summary> /// <param name="nodes">要添加的若干元素</param> /// <returns>添加元素后的当前集合</returns> public MarcNodeList add(MarcNodeList nodes) { // this.m_list.AddRange(nodes); foreach (MarcNode node in nodes) { this.m_list.Add(node); } return(this); }
// 观察 node 是否和集合中的任何一个节点有重叠关系 static bool isCross(MarcNode node, MarcNodeList list) { foreach (MarcNode current in list) { if (isCross(current, node) == true) { return(true); } } return(false); }
/// <summary> /// 把记录中的 880 字段聚集在一起 /// </summary> /// <param name="record">MARC 记录</param> public static void PositionField880s(MarcRecord record) { MarcNodeList fields = record.select("field[@name='880']"); fields.detach(); foreach (MarcField field in fields) { record.ChildNodes.insertSequence(field, InsertSequenceStyle.PreferTail); } }
// 复制出一个新的集合 // 注意,不但数组(框架)被复制,其中每个元素都重新复制 /// <summary> /// 根据当前集合复制出一个新的集合对象。本方法采取的是否深度复制策略,即新集合中的每个元素都是复制品 /// </summary> /// <returns>新的集合</returns> public MarcNodeList clone() { MarcNodeList result = new MarcNodeList(); foreach (MarcNode node in this) { result.add(node.clone()); } return(result); }
// 返回最后一个元素 /// <summary> /// 获得当前集合的最后一个元素 /// </summary> /// <returns>当前集合的最后一个元素(所构成的一个新集合)</returns> public MarcNodeList last() { MarcNodeList results = new MarcNodeList(); if (this.count > 0) { results.add(this[this.count - 1]); } return(results); }
// 返回某个元素 /// <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); }
// 给 MARC21 的若干子字段添加正确的标点符号 /// <summary> /// 给 MARC21 的若干子字段添加正确的标点符号 /// </summary> /// <param name="record">MARC 记录</param> /// <param name="strStyle">风格</param> /// <returns>记录是否发生了修改</returns> public static bool PunctuationMarc21(MarcRecord record, string strStyle) { bool bChanged = false; MarcNodeList fields = record.select("field[@name='245']"); foreach (MarcField field in fields) { if (PunctuationMarc21Field245(field, strStyle) == true) { bChanged = true; } } return(bChanged); }
// 从数组中移走全部对象 // 注意,本函数并不修改所移走的对象的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); }
/// <summary> /// 设置指定名字的第一个字段的指示符和内容。如果没有这个字段,则创建一个 /// </summary> /// <param name="strFieldName">字段名。3字符</param> /// <param name="strIndicator">要设置的指示符。如果不想修改指定字段的指示符,则可以将本参数设置为 null;否则应当是一个 2 字符的字符串。如果要操作的字段是控制字段,则本参数不会被使用,可设置为 null</param> /// <param name="strContent">要设置的字段内容。如果是非控制字段,本参数中一般需要按照 MARC 格式要求包含子字段符号(MarcQuery.SUBFLD),以指定子字段名等</param> /// <param name="strNewIndicator">如果指定的字段不存在,则需要创建,创建的时候将采用本参数作为字段指示符的值。控制字段(因为没有指示符所以)不使用本参数。如果本参数设置为 null,但函数执行过程中确实遇到了需要创建新字段的情况,则函数会自动采用两个空格作为新字段的指示符</param> public void setFirstField( string strFieldName, string strIndicator, string strContent, string strNewIndicator = null) { // 检查参数 if (string.IsNullOrEmpty(strFieldName) == true || strFieldName.Length != 3) { throw new ArgumentException("strFieldName不能为空,应是 3 字符内容", "strFieldName"); } if (string.IsNullOrEmpty(strIndicator) == false && strIndicator.Length != 2) { throw new ArgumentException("strIndicator若不是空,应是 2 字符内容", "strIndicator"); } if (string.IsNullOrEmpty(strNewIndicator) == false && strNewIndicator.Length != 2) { throw new ArgumentException("strNewIndicator若不是空,应是 2 字符内容", "strNewIndicator"); } MarcNodeList fields = this.select("field[@name='" + strFieldName + "']"); if (fields.count == 0) { if (isControlFieldName(strFieldName) == true) { this.ChildNodes.insertSequence(new MarcField(strFieldName, strContent)); } else { if (string.IsNullOrEmpty(strNewIndicator) == true) { strNewIndicator = " "; } this.ChildNodes.insertSequence(new MarcField(strFieldName, strNewIndicator, strContent)); } } else { if (string.IsNullOrEmpty(strIndicator) == false) { fields[0].Indicator = strIndicator; } fields[0].Content = strContent; } }
// 根据字段名和 $6 内容寻找字段 // parameters: // strFieldName 要找的字段的字段名 // strFieldName6 $6 子字段里面的字段名 static MarcField _findField( MarcRecord record, string strFieldName, string strFieldName6, string strNumber, bool bMainField = true) { MarcNodeList fields = record.select("field[@name='" + strFieldName + "']"); foreach (MarcField field in fields) { string content_6 = field.select("subfield[@name='6']").FirstContent; if (string.IsNullOrEmpty(content_6) == true) { continue; } // 拆解 $6 内容 string strCurFieldName = ""; string strCurNumber = ""; string strScriptId = ""; string strOrentation = ""; _parseSubfield6(content_6, out strCurFieldName, out strCurNumber, out strScriptId, out strOrentation); if (string.IsNullOrEmpty(strScriptId) == false && bMainField == true) { continue; } if (string.IsNullOrEmpty(strScriptId) == true && bMainField == false) { continue; } if (strCurFieldName == strFieldName6 && strCurNumber == strNumber) { return(field); } } return(null); }
// 在目标集合中每个元素的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++; } }
/// <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++; } }
// 在目标集合中每个元素的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++; } }
// 获得一个未使用过的字段连接编号 static string _getNewNumber(MarcRecord record) { List <string> numbers = new List <string>(); MarcNodeList subfields = record.select("field/subfield[@name='6']"); foreach (MarcSubfield subfield in subfields) { // 拆解 $6 内容 string strFieldName = ""; string strNumber = ""; string strScriptId = ""; string strOrientation = ""; _parseSubfield6(subfield.Content, out strFieldName, out strNumber, out strScriptId, out strOrientation); if (string.IsNullOrEmpty(strNumber) == false) { numbers.Add(strNumber); } } if (numbers.Count == 0) { return("01"); } numbers.Sort(); string strMaxNumber = numbers[numbers.Count - 1]; int nMax = 0; if (Int32.TryParse(strMaxNumber, out nMax) == false) { throw new Exception("字段编号 '" + strMaxNumber + "' 格式错误,应该为二位数字"); } if (nMax < 0 || nMax > 98) { throw new Exception("已有最大字段编号 '" + strMaxNumber + "' 格式错误,应该为二位数字,值在 00-98 之间"); } return((nMax + 1).ToString().PadLeft(2, '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); }
/// <summary> /// 设置指定名字的第一个字段和第一个子字段的值。如果没有这个字段,则创建一个;如果没有这个子字段,则创建一个 /// </summary> /// <param name="strFieldName">字段名。3字符</param> /// <param name="strSubfieldName">子字段名。1字符</param> /// <param name="strContent">要设置的子字段内容</param> /// <param name="strNewIndicator">如果指定的字段不存在,则需要创建,创建的时候将采用本参数作为字段指示符的值</param> public void setFirstSubfield( string strFieldName, string strSubfieldName, string strContent, string strNewIndicator = " ") { // 检查参数 if (string.IsNullOrEmpty(strFieldName) == true || strFieldName.Length != 3) { throw new ArgumentException("strFieldName不能为空,应是 3 字符内容", "strFieldName"); } if (string.IsNullOrEmpty(strSubfieldName) == true || strSubfieldName.Length != 1) { throw new ArgumentException("strSubfieldName不能为空,应是 1 字符内容", "strSubfieldName"); } if (string.IsNullOrEmpty(strNewIndicator) == true || strNewIndicator.Length != 2) { throw new ArgumentException("strNewIndicator不能为空,应是 2 字符内容", "strNewIndicator"); } MarcNodeList fields = this.select("field[@name='" + strFieldName + "']"); if (fields.count == 0) { this.ChildNodes.insertSequence(new MarcField(strFieldName, strNewIndicator, MarcQuery.SUBFLD + strSubfieldName + strContent)); } else { MarcNodeList subfields = fields[0].select("subfield[@name='" + strSubfieldName + "']"); if (subfields.count == 0) { fields[0].ChildNodes.insertSequence(new MarcSubfield(strSubfieldName, // bug "a", strContent)); } else { subfields[0].Content = strContent; } } }
// 在当前集合中每个元素的DOM位置 下级开头 插入新元素 // 参见 MarcQuery::prepend() 函数的注释 // 最后返回当前集合 /// <summary> /// 在当前集合的每个元素的 DOM 位置的下级开头插入根据指定的源字符串构造的新元素 /// </summary> /// <param name="strSourceText">源字符串</param> /// <returns>当前集合</returns> public MarcNodeList prepend(string strSourceText) { if (this.count == 0 || string.IsNullOrEmpty(strSourceText)) { return(this); } if (this[0].NodeType == NodeType.None) { throw new ArgumentException("不允许在 None 节点的 下级开头 添加任何节点"); } if (this[0].NodeType == NodeType.Subfield) { throw new ArgumentException("不允许在 子字段 节点的 下级开头 添加任何节点。因为子字段本身就是末级节点,不允许出现下级节点"); } MarcNodeList source_nodes = null; string strLeading = ""; if (this[0].NodeType == NodeType.Record) { source_nodes = MarcQuery.createFields(strSourceText); } else if (this[0].NodeType == NodeType.Field) { source_nodes = MarcQuery.createSubfields(strSourceText, out strLeading); // leading要追加到目标集合的最后一个元素的Content末尾 if (string.IsNullOrEmpty(strLeading) == false) { this.last()[0].Content += strLeading; } } else { throw new Exception("未知的对象类型 '" + this[0].NodeType.ToString() + "'"); } MarcQuery.prepend(source_nodes, this); return(this); }
// 在当前集合中每个元素的DOM位置后面插入新元素 // 参见 MarcQuery::insertAfter() 函数的注释 // 最后返回当前集合 /// <summary> /// 在当前集合中每个元素的 DOM 位置后面插入新元素,新元素由指定的源字符串构造 /// </summary> /// <param name="strSourceText">源字符串</param> /// <returns>当前集合</returns> public MarcNodeList after(string strSourceText) { if (this.count == 0 || string.IsNullOrEmpty(strSourceText)) { return(this); } if (this[0].NodeType == NodeType.None) { throw new ArgumentException("不允许在 None 对象的后面添加任何对象"); } if (this[0].NodeType == NodeType.Record) { throw new ArgumentException("不允许在 记录 对象的后面添加任何对象"); } MarcNodeList source_nodes = null; string strLeading = ""; if (this[0].NodeType == NodeType.Field) { source_nodes = MarcQuery.createFields(strSourceText); } else { source_nodes = MarcQuery.createSubfields(strSourceText, out strLeading); // leading要追加到目标集合的最后一个元素的Content末尾 if (string.IsNullOrEmpty(strLeading) == false) { this.last()[0].Content += strLeading; } } MarcQuery.insertAfter(source_nodes, this); return(this); }
// 在当前集合中每个元素的DOM位置后面插入源集合内的元素 // 参见 MarcQuery::insertAfter() 函数的注释 // 最后返回当前集合 /// <summary> /// 在当前集合中每个元素的 DOM 位置后面插入指定的源集合内的元素 /// </summary> /// <param name="source_nodes">源集合</param> /// <returns>当前集合</returns> public MarcNodeList after(MarcNodeList source_nodes) { MarcQuery.insertAfter(source_nodes, this); return(this); }
/// <summary> /// 在当前集合中每个元素的 DOM 位置前面插入指定的源集合内的元素 /// </summary> /// <param name="source_nodes">源集合</param> /// <returns>当前集合</returns> public MarcNodeList before(MarcNodeList source_nodes) { MarcQuery.insertBefore(source_nodes, this); return(this); }
/// <summary> /// 将当前集合内的全部元素插入到指定的目标集合的 DOM 位置下级开头 /// </summary> /// <param name="target_nodes">目标集合</param> /// <returns>当前集合</returns> public MarcNodeList prependTo(MarcNodeList target_nodes) { MarcQuery.prepend(this, target_nodes); return(this); }