// 根据字段权限定义过滤出允许的内容 // return: // -1 出错 // 0 成功 // 1 有部分字段被修改或滤除 public static int FilterFields(string strFieldNameList, ref string strMarc, out string strError) { strError = ""; int nRet = 0; bool bChanged = false; if (string.IsNullOrEmpty(strMarc) == true) return 0; string strHeader = ""; string strBody = ""; SplitMarc(strMarc, out strHeader, out strBody); if (strHeader.Length < 24) { strHeader = strHeader.PadRight(24, '?'); bChanged = true; } FieldNameList list = new FieldNameList(); nRet = list.Build(strFieldNameList, out strError); if (nRet == -1) { strError = "字段权限定义 '"+strFieldNameList+"' 不合法: " + strError; return -1; } StringBuilder text = new StringBuilder(4096); if (list.Contains("###") == true) text.Append(strHeader); else { bChanged = true; text.Append(new string('?', 24)); } string[] fields = strBody.Split(new char[] {(char)30}, StringSplitOptions.RemoveEmptyEntries); foreach (string s in fields) { if (string.IsNullOrEmpty(s) == true) continue; string strFieldName = GetFieldName(s); if (list.Contains(strFieldName) == false) { bChanged = true; continue; } text.Append(s); text.Append((char)30); } strMarc = text.ToString(); if (bChanged == true) return 1; return 0; }
// 根据允许的字段名列表,合并新旧两条书目记录 // 列表中不允许的字段,沿用旧记录中的原始字段内容 // 算法等于在 new 中复原了那些不让修改的 MARC 字段 static int MergeOldNewBiblioByFieldNameList( string strFieldNameList, string strOldBiblioXml, ref string strNewBiblioXml, out string strError) { strError = ""; int nRet = 0; XmlDocument domNew = new XmlDocument(); if (String.IsNullOrEmpty(strNewBiblioXml) == true) strNewBiblioXml = "<root />"; try { domNew.LoadXml(strNewBiblioXml); } catch (Exception ex) { strError = "strNewBiblioXml装入XMLDOM时出错: " + ex.Message; return -1; } string strNewSave = domNew.OuterXml; XmlDocument domOld = new XmlDocument(); if (String.IsNullOrEmpty(strOldBiblioXml) == true || (string.IsNullOrEmpty(strOldBiblioXml) == false && strOldBiblioXml.Length == 1)) strOldBiblioXml = "<root />"; try { domOld.LoadXml(strOldBiblioXml); } catch (Exception ex) { strError = "strOldBiblioXml装入XMLDOM时出错: " + ex.Message; return -1; } string strMarcSyntax = ""; // 探测MARC格式 // return: // -1 error // 0 无法探测 // 1 探测到了 nRet = DetectMarcSyntax(domNew, out strMarcSyntax, out strError); if (nRet == -1) return -1; if (nRet == 0) { nRet = DetectMarcSyntax(domOld, out strMarcSyntax, out strError); if (nRet == -1) return -1; if (nRet == 0) { strError = "无法探测到 MARC 格式"; return -1; } } FieldNameList list = new FieldNameList(); nRet = list.Build(strFieldNameList, out strError); if (nRet == -1) return -1; XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); nsmgr.AddNamespace("unimarc", Ns.unimarcxml); nsmgr.AddNamespace("usmarc", Ns.usmarcxml); XmlNode old_root = domOld.DocumentElement.SelectSingleNode("//" + strMarcSyntax + ":record", nsmgr); if (old_root == null) { // 对 new 过滤出全部可以修改的字段即可 XmlNodeList new_nodes = domNew.DocumentElement.SelectNodes("//" + strMarcSyntax + ":leader | //" + strMarcSyntax + ":controlfield | //" + strMarcSyntax + ":datafield", nsmgr); foreach (XmlNode node in new_nodes) { XmlElement element = (XmlElement)node; string strTag = GetTag(element); // TODO:如果连头标区也要滤除,要保留一个缺省值的头标区 if (list.Contains(strTag) == false && strTag != "###") node.ParentNode.RemoveChild(node); } strNewBiblioXml = domNew.DocumentElement.OuterXml; return 0; } XmlNode new_root = domNew.DocumentElement.SelectSingleNode("//" + strMarcSyntax + ":record", nsmgr); if (new_root == null) { // new 里面没有任何 MARC 字段,因此不必作了 return 0; } // 1) 把 new 中的 不允许修改的字段标记出来 List<XmlNode> reserve_nodes = new List<XmlNode>(); { XmlNodeList new_nodes = domNew.DocumentElement.SelectNodes("//" + strMarcSyntax + ":leader | //" + strMarcSyntax + ":controlfield | //" + strMarcSyntax + ":datafield", nsmgr); foreach (XmlNode node in new_nodes) { XmlElement element = (XmlElement)node; string strTag = GetTag(element); if (list.Contains(strTag) == false) reserve_nodes.Add(element); } } // 2) 从 old 中把全部不允许修改的字段对应位置一个一个覆盖 new 中的对应字段。如果在 new 中没有找到对应字段,在插入在最后一个同名字段后面,如果没有同名字段,则插入到适当的顺序位置 XmlNodeList old_nodes = domOld.DocumentElement.SelectNodes("//" + strMarcSyntax + ":leader | //" + strMarcSyntax + ":controlfield | //" + strMarcSyntax + ":datafield", nsmgr); foreach (XmlNode node in old_nodes) { XmlElement element = (XmlElement)node; string strTag = GetTag(element); if (list.Contains(strTag) == true) continue; XmlElement last_same_name_node = null; // 在另一边(nodes内)寻找对应的字段元素 // parameters: // last_same_name_node 最后一个同tag名的元素 XmlElement target = FindElement(element, new_root, out last_same_name_node); if (target != null) { target.InnerXml = element.InnerXml; if (target.LocalName == "datafield") { // 还要修改 ind1 ind2 属性 target.SetAttribute("ind1", element.GetAttribute("ind1")); target.SetAttribute("ind2", element.GetAttribute("ind2")); } reserve_nodes.Remove(target); continue; } if (last_same_name_node != null) { last_same_name_node.InsertAfter(domNew.ImportNode(element, true), last_same_name_node); continue; } // 找到一个合适的位置插入 insertSequence(element, new_root); } // 3) 在 new 中把没有被覆盖的标记了的字段全部删除 foreach (XmlNode node in reserve_nodes) { node.ParentNode.RemoveChild(node); } strNewBiblioXml = domNew.DocumentElement.OuterXml; return 0; }