// 处理一条记录对应于一个<record>定义 // container参数完全可能为null,这表示<record>为根元素 // return: // -1 出错 // 0 正常返回 int DoSingleItem( object objParam, XmlNode node, int nIndex, FilterItem container, string strData, string strNextName, out BreakType breakType, out string strError) { strError = ""; breakType = BreakType.None; /* Debug.Assert(node != null, "node参数不能为null"); HashFilterItem itemNode = (HashFilterItem)NodeTable[node]; if (itemNode == null) { Debug.Assert(false, "NodeTable中缺乏事项"); return -1; } Debug.Assert(node == itemNode.xmlNode, "item成员xmlNode不正确"); Type entryClassType = itemNode.FunctionType; if (entryClassType == null) { Debug.Assert(false, itemNode.FunctionName + "没有预先填充Type"); return -1; } // 把fltx.cs代码中的Batch层对象new,并保持 // new一个Batch派生对象 FilterItem itemHost = (FilterItem)entryClassType.InvokeMember(null, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, null); */ // 创建一个新FilterItem对象 FilterItem itemHost = NewFilterItem( objParam, node, out strError); if (itemHost == null) return -1; itemHost.Data = strData; itemHost.Index = nIndex; itemHost.Container = container; // itemHost.FilterRoot = container != null ? container : itemHost; itemHost.FilterRoot = GetRootFilterItem(itemHost); Debug.Assert(itemHost.FilterRoot != null, "itemHost.FilterRoot不应当==null"); if (node.Name == "record") { itemHost.NodeType = NodeType.Record; itemHost.Data = strData; itemHost.Name = ""; itemHost.Content = strData; } else if (node.Name == "field") { itemHost.NodeType = NodeType.Field; itemHost.Data = strData; if (strData.Length < 3) { strError = "字段全部数据长度不足3字符"; goto ERROR1; } itemHost.Name = strData.Substring(0, 3); // 这里要求调用本函数的,准备头标区这个特殊“字段”时,要加上'hdr'2字符在内容前面 // control field 001-009没有子字段 if (FilterItem.IsControlFieldName(itemHost.Name) == true) { itemHost.Indicator = ""; itemHost.Content = strData.Substring(3); } else { if (strData.Length >= 5) { itemHost.Indicator = strData.Substring(3, 2); itemHost.Content = strData.Substring(5); } else { // 2006/11/24 itemHost.Indicator = ""; itemHost.Content = ""; } } } else if (node.Name == "group") { itemHost.NodeType = NodeType.Group; itemHost.Data = strData; itemHost.Name = ""; itemHost.Content = strData; } else if (node.Name == "subfield") { itemHost.NodeType = NodeType.Subfield; itemHost.Data = strData; if (strData.Length < 1) { strError = "子字段全部数据长度不足1字符"; goto ERROR1; } itemHost.Name = strData.Substring(0, 1); itemHost.Content = strData.Substring(1); } itemHost.SetDupCount(); itemHost.NextName = strNextName; if (itemHost.Container != null) { itemHost.PrevName = itemHost.Container.LastChildName; // 利用上次遗留的 // 这一句有点多余。因为本函数返回后, 后面立即会做修改LastChildName的事情 itemHost.Container.LastChildName = itemHost.Name; // 保存这次的 } itemHost.OnBegin(); // 检查无意义的break设置情况 if (CheckBreakException == true && node.Name == "subfield" && (itemHost.Break == BreakType.SkipCaseEnd || itemHost.Break == BreakType.SkipCase) ) { throw(new Exception("<subfield>元素内script代码中用Break = ???改变结构匹配流程无任何意义...")); } if (itemHost.Break == BreakType.SkipCaseEnd) goto SKIP1; // 不做OnEnd() if (itemHost.Break == BreakType.SkipCase) goto SKIP; // 不做OnBegin的兄弟case,但是要做OnEnd() // int i; int nRet; // XmlNode child = null; BreakType thisBreak = BreakType.None; // <record>希望下级是<field> if (node.Name == "record") { // 切割记录为若干字段,匹配case for(int r=0;;r++) { string strField; string strNextFieldName; // 从记录中得到一个字段 // parameters: // strMARC MARC记录 // strFieldName 字段名。如果==null,表示任意字段 // nIndex 同名字段中的第几个。从0开始计算(0表示头标区) // strField [out]输出字段。包括字段名、必要的字段指示符、字段内容。不包含字段结束符。 // 注意头标区当作一个字段返回,strField中不包含字段名,一上来就是头标区内容 // return: // -1 error // 0 not found // 1 found nRet = MarcDocument.GetField(strData, null, r, out strField, out strNextFieldName); if (nRet == -1) { // 2009/11/1 if (String.IsNullOrEmpty(strData) == true) break; strError = "DoSingleItem() GetField() error"; return -1; } if (nRet == 0) break; if (strField.Length < 3) goto SKIP; string strFieldName = ""; if (r != 0) strFieldName = strField.Substring(0,3); else { strFieldName = "hdr"; strField = strFieldName + strField; } // *** itemHost.IncChildDupCount(strFieldName); // for(i=0;i<node.ChildNodes.Count;i++) foreach(XmlNode child in node.ChildNodes) { // child = node.ChildNodes[i]; if (child.NodeType != XmlNodeType.Element) continue; if (child.Name != "field") continue; // 匹配字段名 nRet = MatchName( strFieldName, DomUtil.GetAttr(child, "name")); if (nRet == 1) { nRet = DoSingleItem( objParam, child, r, itemHost, strField, strNextFieldName, out thisBreak, out strError); if (nRet == -1) return -1; if (itemHost.Break != BreakType.None) break; } } // end of for itemHost.LastChildName = strFieldName; // 保存这次的 if (itemHost.Break != BreakType.None) goto SKIP; } } else if (node.Name == "field") { // 若下级为subfield string strFirstChildName = GetFirstChildElementType(node); // field下的subfield if (strFirstChildName == "subfield") { // 切割记录为若干子字段,匹配case for(int s=0;;s++) { string strSubfield; string strNextSubfieldName; // 从字段或组中得到一个子字段 // parameters: // strText 字段内容,或者子字段组内容。 // textType 表示strText中包含的是字段内容还是组内容。 // strSubfieldName 子字段名。如果==null,表示任意子字段 // 形式为'a'这样的。 // nIndex 同名子字段中的第几个。从0开始计算。 // strSubfield 输出子字段。子字段名(1字符)、子字段内容。 // strNextSubfieldName 下一个子字段的名字,一个字符 // return: // -1 error // 0 not found // 1 found nRet = MarcDocument.GetSubfield(strData, ItemType.Field, null, s, out strSubfield, out strNextSubfieldName); if (nRet == -1) { strError = "GetSubfield() error"; return -1; } if (nRet == 0) break; if (strSubfield.Length < 1) goto SKIP; string strSubfieldName = strSubfield.Substring(0,1); // *** itemHost.IncChildDupCount(strSubfieldName); // for(i=0;i<node.ChildNodes.Count;i++) foreach(XmlNode child in node.ChildNodes) { // child = node.ChildNodes[i]; if (child.NodeType != XmlNodeType.Element) continue; if (child.Name != "subfield") continue; // 匹配子字段名 nRet = MatchName( strSubfieldName, DomUtil.GetAttr(child, "name")); if (nRet == 1) { nRet = DoSingleItem( objParam, child, s, itemHost, strSubfield, strNextSubfieldName, out thisBreak, out strError); if (nRet == -1) return -1; if (itemHost.Break != BreakType.None) break; } } // end of for itemHost.LastChildName = strSubfieldName; // 保存这次的 if (itemHost.Break != BreakType.None) goto SKIP; } } // field下嵌套的field if (strFirstChildName == "field") { // 切割字符串为若干字段,匹配case for(int r=0;;r++) { string strField; string strNextFieldName; // 从记录中得到一个字段 // parameters: // strMARC MARC记录 // strFieldName 字段名。如果==null,表示任意字段 // nIndex 同名字段中的第几个。从0开始计算(0表示头标区) // strField [out]输出字段。包括字段名、必要的字段指示符、字段内容。不包含字段结束符。 // 注意头标区当作一个字段返回,strField中不包含字段名,一上来就是头标区内容 // return: // -1 error // 0 not found // 1 found nRet = MarcDocument.GetNestedField(strData, null, r, out strField, out strNextFieldName); if (nRet == -1) { strError = "GetNestedField() error"; return -1; } if (nRet == 0) break; if (strField.Length < 3) goto SKIP; string strFieldName = ""; strFieldName = strField.Substring(0,3); // *** itemHost.IncChildDupCount(strFieldName); // 嵌套字段不存在头标区'hdr'字段问题? //for(i=0;i<node.ChildNodes.Count;i++) foreach(XmlNode child in node.ChildNodes) { //child = node.ChildNodes[i]; if (child.NodeType != XmlNodeType.Element) continue; if (child.Name != "field") continue; // 匹配字段名 nRet = MatchName( strFieldName, DomUtil.GetAttr(child, "name")); if (nRet == 1) { nRet = DoSingleItem( objParam, child, r, itemHost, strField, strNextFieldName, out thisBreak, out strError); if (nRet == -1) return -1; if (itemHost.Break != BreakType.None) break; } } // end of for itemHost.LastChildName = strFieldName; // 保存这次的 if (itemHost.Break != BreakType.None) goto SKIP; } } // field 下的group else if (strFirstChildName == "group") { // 切割记录为若干子字段,匹配case for(int g=0;;g++) { string strGroup; // 从字段中得到子字段组 // parameters: // strGroup [out]结果。 // return: // -1 error // 0 not found // 1 found nRet = MarcDocument.GetGroup(strData, g, out strGroup); if (nRet == -1) { strError = "GetGroup() error"; return -1; } if (nRet == 0) break; string strGroupName = Convert.ToString(g); // *** itemHost.IncChildDupCount(strGroupName); // for(i=0;i<node.ChildNodes.Count;i++) foreach(XmlNode child in node.ChildNodes) { // child = node.ChildNodes[i]; if (child.NodeType != XmlNodeType.Element) continue; if (child.Name != "group") continue; // 匹配组名 nRet = MatchName( strGroupName, DomUtil.GetAttr(child, "name")); if (true/*nRet == 1*/) { nRet = DoSingleItem( objParam, child, g, itemHost, strGroup, "", out thisBreak, out strError); if (nRet == -1) return -1; if (itemHost.Break != BreakType.None) break; } } // end of for itemHost.LastChildName = ""; // 保存这次的 if (itemHost.Break != BreakType.None) goto SKIP; } } } else if (node.Name == "group") { // 若下级为subfield string strFirstChildName = GetFirstChildElementType(node); if (strFirstChildName != "subfield") { strError = ".fltx中<group>下级必须为<subfield>元素"; return -1; } // 切割记录为若干子字段,匹配case for(int s=0;;s++) { string strSubfield; string strNextSubfieldName; // 从字段或组中得到一个子字段 // parameters: // strText 字段内容,或者子字段组内容。 // textType 表示strText中包含的是字段内容还是组内容。 // strSubfieldName 子字段名。如果==null,表示任意子字段 // 形式为'a'这样的。 // nIndex 同名子字段中的第几个。从0开始计算。 // strSubfield 输出子字段。子字段名(1字符)、子字段内容。 // strNextSubfieldName 下一个子字段的名字,一个字符 // return: // -1 error // 0 not found // 1 found nRet = MarcDocument.GetSubfield(strData, ItemType.Group, null, s, out strSubfield, out strNextSubfieldName); if (nRet == -1) { strError = "GetSubfield() error"; return -1; } if (nRet == 0) break; if (strSubfield.Length < 1) goto SKIP; string strSubfieldName = strSubfield.Substring(0,1); // *** itemHost.IncChildDupCount(strSubfieldName); // for(i=0;i<node.ChildNodes.Count;i++) foreach (XmlNode child in node.ChildNodes) { // child = node.ChildNodes[i]; if (child.NodeType != XmlNodeType.Element) continue; if (child.Name != "subfield") continue; // 匹配子字段名 nRet = MatchName( strSubfieldName, DomUtil.GetAttr(child, "name")); if (nRet == 1) { nRet = DoSingleItem( objParam, child, s, itemHost, strSubfield, strNextSubfieldName, out thisBreak, out strError); if (nRet == -1) return -1; if (itemHost.Break != BreakType.None) break; } } // end of for itemHost.LastChildName = strSubfieldName; // 保存这次的 if (itemHost.Break != BreakType.None) goto SKIP; } } else if (node.Name == "subfield") { // 暂时没有什么处理 } SKIP: if (itemHost.Break != BreakType.SkipCaseEnd) { itemHost.OnEnd(); } SKIP1: /* if (itemHost.Break != BreakType.None) return 1; */ breakType = itemHost.Break; return 0; ERROR1: return -1; }
FilterItem GetRootFilterItem(FilterItem start) { FilterItem item = start; for(;item!=null;) { if (item.FilterRoot == item) return item; item = item.Container; } return null; }