常用的MarcQuery脚本集锦
MarcQuery 脚本使用方法 https://github.com/DigitalPlatform/dp2/wiki/MarcQuery-脚本使用方法
MarcQuery 函数库的参考手册:http://dp2003.com/marcquery/
如何在 dp2catalog 中执行 MarcQuery 脚本? https://github.com/DigitalPlatform/dp2/issues/344
清空 606$a 子字段内容(dp2circulation)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
// 先检索出606$a子字段
MarcNodeList subfields = this.MarcRecord.select("field[@name='606']/subfield[@name='a']");
foreach (MarcNode node in subfields)
{
node.Content = ""; // 将606$a子字段内容设为空
this.Changed = true; //将这条记录标识修改状态,这样后面可以保存修改。
}
}
}
删除 606$a 子字段
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
MarcNodeList subfields = this.MarcRecord.select("field[@name='606']/subfield[@name='a']");
foreach (MarcNode node in subfields)
{
node.detach(); // 删除子字段
this.Changed = true;
}
}
}
新增一个 801 字段
下面代码可以给 MARC 记录无条件新增一个 801 字段:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
this.MarcRecord.ChildNodes.insertSequence(new MarcField('$', "801 $aCN$bNLC"));
this.Changed = true;
}
}
而如果是当 801 字段存在的时候修改它,不存在的时候新增一个 801,可以这样写:
public override void OnRecord(object sender, StatisEventArgs e)
{
MarcNodeList fields = this.MarcRecord.select("field[@name='801']");
if (fields.count >0)
{
MarcNodeList subfields = fields[0].select("subfield[@name='a']");
if (subfields.count > 0)
subfields.Content = "CN";
else
fields[0].ChildNodes.insertSequence(new MarcSubfield("a", "CN"));
subfields = fields[0].select("subfield[@name='b']");
if (subfields.count > 0)
subfields.Content = "NLC";
else
fields[0].ChildNodes.insertSequence(new MarcSubfield("b", "NLC"));
}
else
this.MarcRecord.ChildNodes.insertSequence(new MarcField('$', "801 $aCN$bNLC"));
this.Changed = true;
}
这段代码比较复杂。
考虑到这种“有了一个字段(子字段)就修改它,没有就新增一个”的需求特别常见,MarcQuery 甚至提供了一个专门的 setFirstField() 或者 setFirstSubfield() 函数: 注:这一段脚本暴露了当前 MarcQuery 函数库一个 bug
public override void OnRecord(object sender, StatisEventArgs e)
{
this.MarcRecord.setFirstSubfield("801", "a", "CN", " ");
this.MarcRecord.setFirstSubfield("801", "b", "NLC", " ");
this.Changed = true;
}
(MarcRecord类)setFirstSubfield() 函数原型如下:
/// <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 = " ")
在MARC记录的998$s子字段作标识 (dp2circulation)
using System;
using System.Windows.Forms;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Text;
public class add998s : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
string value = "***"; //这里输入标识值
// 先检索出998字段
MarcNodeList fields = this.MarcRecord.select("field[@name=998]");
// 如果不存在998字段,直接增加998 $s
if (fields.count == 0)
{
this.MarcRecord.append(String.Format("998 {0}s{1}", MarcQuery.SUBFLD, value));
this.Changed = true;
return;
}
// 取第一个998节点的$s子字段
MarcNode node = fields[0];
MarcNodeList subfields = node.select("subfield[@name='s']");
// 如果没有$s子字段,增加998 $s
if (subfields.count == 0)
{
node.append(String.Format("{0}s{1}", MarcQuery.SUBFLD, value));
this.Changed = true;
return;
}
// 取第一个998$s子字段
MarcNode sNode = subfields[0];
string sContent= sNode.Content;
string old = sContent; //值
StringUtil.SetInList(ref sContent, value, true); //新值
//MessageBox.Show("old="+old +" new=" + sContent);
// 如果新旧值不等,标记为修改状态
if (old != sContent)
{
sNode.Content = sContent;
this.Changed = true;
return;
}
}
}
DigitalPlatform.Text.dll 的 SetInList()函数
// 在列举值中增加或清除一个值
// parameters:
// strSub 里面可以包含多个值
public static void SetInList(ref string strList,
string strSub,
bool bOn)
{
if (bOn == false)
{
RemoveFromInList(strSub,
true,
ref strList);
}
else
{
// 单个值的情况
if (strSub.IndexOf(',') == -1)
{
if (IsInList(strSub, strList) == true)
return; // 已经有了
// 在尾部新增加
if (string.IsNullOrEmpty(strList) == false)
strList += ",";
strList += strSub;
return;
}
// 2012/2/2
// 多个值的情况
string[] sub_parts = strSub.Split(new char[] { ',' });
foreach (string sub in sub_parts)
{
if (sub == null)
continue;
string strOne = sub.Trim();
if (string.IsNullOrEmpty(strOne) == true)
continue;
if (IsInList(strOne, strList) == true)
continue; // 已经有了
// 在尾部新增加
if (string.IsNullOrEmpty(strList) == false)
strList += ",";
strList += strOne;
}
}
}
补充一下:上面的 MarcQuery 脚本可以作为一个很好的培训练习题材。示范在内务书目查询窗中,如何二次开发 MarcQuery 脚本。 但就“修改书目记录 998$s” 这个功能来说,内务的书目查询窗内是本来就有这个功能的。即浏览列表中上下文菜单中的“快速修改书目记录”功能。这个功能挺完备的,它可以为 998$s 添加或者去掉一个子串,而保留其他子串。 注:998$s 内容,也就是书目记录的“状态”字段,里面可以是这样的形态“子串1,子串2”。
原贴地址 https://github.com/DigitalPlatform/dp2/issues/229
输出到 Excel 文件(用 ClosedXML 函数库实现)
创建一个名为 output_excel.cs 的文件:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform;
using DigitalPlatform.Core;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
using ClosedXML.Excel;
public class MyMarcQueryHost : MarcQueryHost
{
SaveFileDialog dlg = new SaveFileDialog();
XLWorkbook doc = null;
IXLWorksheet sheet = null;
int nRowIndex = 1; // 行号
public override void OnBegin(object sender, StatisEventArgs e)
{
// 询问文件名
dlg.Title = "请指定要输出的 Excel 文件名";
dlg.CreatePrompt = false;
dlg.OverwritePrompt = true;
dlg.Filter = "Excel 文件 (*.xlsx)|*.xlsx|All files (*.*)|*.*";
dlg.RestoreDirectory = true;
if (dlg.ShowDialog() != DialogResult.OK)
{
e.Continue = ContinueType.SkipAll;
return;
}
try
{
doc = new XLWorkbook(XLEventTracking.Disabled);
File.Delete(dlg.FileName);
}
catch (Exception ex)
{
e.ParamString = ExceptionUtil.GetAutoText(ex);
e.Continue = ContinueType.Error;
return;
}
sheet = doc.Worksheets.Add("表格");
// 输出标题行
{
int nColIndex = 1; // 列号
sheet.Cell(nRowIndex, nColIndex++).SetValue("title");
sheet.Cell(nRowIndex, nColIndex++).SetValue("author");
sheet.Cell(nRowIndex, nColIndex++).SetValue("publisher");
sheet.Cell(nRowIndex, nColIndex++).SetValue("publish time");
nRowIndex++;
}
}
public override void OnRecord(object sender, StatisEventArgs e)
{
int nColIndex = 1; // 列号
string title = this.MarcRecord.select("field[@name='200']/subfield[@name='a']").FirstContent;
sheet.Cell(nRowIndex, nColIndex++).SetValue(title);
string author = this.MarcRecord.select("field[@name='200']/subfield[@name='f']").FirstContent;
sheet.Cell(nRowIndex, nColIndex++).SetValue(author);
string publisher = this.MarcRecord.select("field[@name='210']/subfield[@name='c']").FirstContent;
sheet.Cell(nRowIndex, nColIndex++).SetValue(publisher);
string publish_time = this.MarcRecord.select("field[@name='210']/subfield[@name='d']").FirstContent;
sheet.Cell(nRowIndex, nColIndex++).SetValue(publish_time);
nRowIndex++;
}
public override void OnEnd(object sender, StatisEventArgs e)
{
doc.SaveAs(dlg.FileName);
doc.Dispose();
try
{
System.Diagnostics.Process.Start(dlg.FileName);
}
catch
{
}
}
}
还要创建一个名为 output_excel.cs.ref 的文件: (和上面的文件一起,两个文件要处于同一个文件夹)
<?xml version="1.0" encoding="utf-8"?>
<root>
<ref>system.data.dll</ref>
<ref>%bindir%/ClosedXml.dll</ref>
</root>
ClosedXML 是一个开源的 Excel 处理函数库,在这里: https://github.com/ClosedXML/ClosedXML
它的 wiki: https://github.com/ClosedXML/ClosedXML/wiki
主题词字段一些疑问:606内容$a心理学$x论文$x写作$x心理$j指南 甚至有更多个$x,我想修改某个$x的内容如何实现?
00666nam0 2200229 450_ 001008859384 00520180217001401.0 010 ǂa978-7-5596-0929-8ǂb精装ǂdCNY68.00 100 ǂa20180217d2017 em y0chiy0110 ea 1010 ǂachi 102 ǂaCNǂb110000 105 ǂaa z 000yb 106 ǂar 2001 ǂa颠覆者ǂ9dian fu zheǂdǂe周鸿祎自传ǂf周鸿祎,范海涛著ǂgǂhǂi 210 ǂa北京ǂc北京联合出版公司ǂd2017 215 ǂa377页ǂdǂe 6060 ǂa互联网络ǂx企业家ǂx生平事迹ǂx互联网商业ǂx个人创业经历ǂy中国ǂz现代 690 ǂaK825.38=76ǂv5 701 0ǂa周鸿祎ǂ9zhou hong yiǂ4著 701 0ǂa范海涛ǂ9fan hai taoǂ4著 801 0ǂaCNǂb91MARCǂc20180217 998 ǂu2018-08-09 13:17:39Zǂzsupervisor
比如这条数据,我想要修改606的第三个$x内容 如果能够实现对606这个字段下面的所有子字段逐个进行修改时最好的,因为主题词字段多种多样,除了$a,$x还有$j$y$z等这样的
@distinct2010
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
var fields = this.MarcRecord.select("field[@name='606']");
foreach(MarcField field in fields)
{
var subfields =field.select("subfield[@name='x']");
// 修改第三个 $x 子字段内容(注意代码里面下标是从 0 开始的)
if (subfields.count > 2)
{
subfields[2].Content += "---";
this.Changed = true;
}
}
}
}
前面的描述不太清楚,给定一个606字段,606字段的所有自字段内容是fields[0].ChildNodes.Contents[i] 现在有个数组,通过循环修改每个子字段内容
@distinct2010
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
var fields = this.MarcRecord.select("field[@name='606']");
foreach(MarcField field in fields)
{
int i = 0;
foreach(MarcSubfield subfield in field.ChildNodes)
{
subfield.Content = (i++).ToString();
this.Changed = true;
}
}
}
}
//开始删除设置字段 MarcRecord records = new MarcRecord(this.strMarc); string[] DelFields = Settings.Default.DeleteField.Split(','); foreach (string DelField in DelFields) { if (DelField.Length == 3) { MarcNodeList fields = records.select("field[@name='" + DelField + "']"); foreach (MarcNode node in fields) { node.detach(); } } else if (DelField.Length == 4) { string zd = DelField.Substring(0, 3); string zzd = DelField.Substring(3, 1); MarcNodeList subfields = records.select("field[@name='" + zd + "']/subfield[@name='" + zzd + "']"); foreach (MarcNode node in subfields) { node.detach(); } } else { MessageBox.Show("删除字段配置项:" + DelField + " 有误!"); } }
报错:此时FocusedField不可能为null
@distinct2010
上面您给出的代码不完整,没法验证运行。请提供完整的、能在 dp2circulation 或 dp2catalog 中运行的脚本文件内容。
插入若干个同名字段
插入到同名字段的后方:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
for(int i =0;i<10;i++)
{
this.MarcRecord.ChildNodes.insertSequence(new MarcField('$', "801 $aCN"+i.ToString()+"$bNLC"), InsertSequenceStyle.PreferTail);
this.Changed = true;
}
}
}
注意 insertSequence() 函数的第二参数是指定同名字段插入时候的相对位置关系。InsertSequenceStyle.PreferTail 表示插入在同名字段的后面。这个参数可以缺省,默认为 InsertSequenceStyle.PreferHead,也就是插入到同名字段的前面。
其实只要看看 MarcQuery 代码关于这个函数的原型就能发现这个参数。这个函数还有其他参数的版本。
按照字段名(数字)大小对字段进行排序
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
this.MarcRecord.ChildNodes.sort((a, b)=>{
return string.Compare(a.Name, b.Name);
});
this.Changed = true;
}
}
sort() 函数接受一个回调函数。回调函数只需要比较 a 和 b 两个 MarcNode 对象的大小即可,返回一个整数。整数如何返回呢?可以简单理解为 a - b 的值。如果 a 小于 b,那么应该返回负数;相等应该返回 0,a 大于 b 则应该返回一个正数。
按照字段指示符大小对字段进行排序
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
this.MarcRecord.ChildNodes.sort((a, b)=>{
return string.Compare(a.Indicator, b.Indicator);
});
this.Changed = true;
}
}
当然,这个例子没有啥实际意义,只是示范一下如何自由决定排序因素。
把 909 字段里面的 $b 子字段复制到一个 905 字段中
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
// 制造出若干 909 字段
for(int i =0;i<10;i++)
{
this.MarcRecord.ChildNodes.insertSequence(new MarcField('$', "909 $aCN"+i.ToString()+"$bB" + i.ToString()), InsertSequenceStyle.PreferTail);
this.Changed = true;
}
// 新添加一个 905 字段
MarcField field = new MarcField('$', "905 $atest");
this.MarcRecord.ChildNodes.insertSequence(field, InsertSequenceStyle.PreferTail);
// 选择和复制 909$b 子字段,复制到刚才的 905 字段中
MarcNodeList subfields = this.MarcRecord.select("field[@name='909']/subfield[@name='b']");
foreach(MarcSubfield subfield in subfields)
{
field.ChildNodes.insertSequence(subfield.clone(), InsertSequenceStyle.PreferTail);
}
}
}
删除所有9**字段如何实现?
删除所有 9XX 字段
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
this.MarcRecord.select("field[substring(@name,1,1)='9']").detach();
this.Changed = true;
}
}
注意 XPath 的 substring() 函数第二参数 offset 是从 1 开始计数的,比较坑人。
原来 BBS 里面 http://dp2003.com/dp2bbs/article.aspx?board=@__3&id=71 其中的代码修订以后放在这里:
第一个
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Catalog;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
this.MarcRecord.ChildNodes.add(new MarcField("200", " ",SUBFLD + "aAAAA"));
this.MarcRecord.ChildNodes.add(new MarcField("300", " ", SUBFLD + "bBBBB"));
MarcNodeList nodes = this.MarcRecord.select("field[@name='200']");
MessageBox.Show(this.MainForm, nodes.count.ToString());
this.Changed = true;
}
}
第二个:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Catalog;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
this.MarcRecord.ChildNodes.add(new MarcField("200", " ",SUBFLD + "aAAAA"));
this.MarcRecord.ChildNodes.add(new MarcField("300", " ", SUBFLD + "bBBBB"));
MarcNodeList nodes = this.MarcRecord.select("field[@name='200']");
nodes.first().Name = "999"; // 修改了第一个200字段的字段名
this.Changed = true;
}
}
如何修改头标区和指示符呢?
如何修改头标区
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
this.MarcRecord.Header[0, 5] = "77888";
this.MarcRecord.Header[5, 1] = "!";
this.Changed = true;
}
}
请高手写一个这样的脚本,把215▼a罗马数字转阿拉伯数字,例如,215▼axii,变成215▼a12,这是罗马小写的,另一种是罗马大写,例如215▼aVIII,也是转为215▼a8,非常感谢!
把 215$a 中的罗马数字替换为阿拉伯数字
下面脚本要在 dp2catalog 中执行。罗马数字替换为阿拉伯数字的函数未实现全部功能,只示范性替换了 xiii 这个罗马数字。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Catalog;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
var subfields = this.MarcRecord.select("field[@name='215']/subfield[@name='a']");
foreach(MarcSubfield subfield in subfields)
{
string content = subfield.Content;
string new_content = ReplaceText(content);
if (content != new_content)
{
subfield.Content = new_content;
this.Changed = true;
}
}
}
// 把文本中的罗马数字部分替换为阿拉伯数字。未完成
static string ReplaceText(string text)
{
if (string.IsNullOrEmpty(text))
return text;
// TODO: 这里需要实现变换功能
return text.Replace("xiii", "13");
}
}
制作MARC21数据,常常需要转换一些字段内容,如020:$cCNY307.28(GBP29.99) [注:从v3编目marc记录窗复制▼到记事本变成了$,在复制$到记录窗没有变回▼],如何通过脚本把已经制作好的txt文件批加入,如文本文件制作好,9783944874593 :▼cCNY461.07(GBP45.00) [注:前面冒号必加] ,把▼c准确无误的加入对应数据020字段▼a9783944874593的后面
符号转化对应上了 9780190904913 :|cCNY266.29(GBP25.99) 9780190906801 :|cCNY491.71(GBP47.99) 9780190908904 :|cCNY655.74(GBP64.00) 9780190909376 :|cCNY563.53(GBP55.00) 9780190913151 :|cCNY491.71(GBP47.99)脚本如何写还是个问题?????????????????????????? 01331cam a2200325 i 4500 00120415204 00520190523125802.0 008180321s2018 nyu b 001 0 eng__ 010 ǂa 2018013235 020 ǂa9780190904913 (hardcover)【注:把文本文件内容或excel的:|cCNY266.29(GBP25.99)加到这里来】 020 ǂz9780190904920 (updf) 020 ǂz9780190904937 (ebook) 040 ǂaDLCǂbengǂcDLCǂerdaǂdDLC 042 ǂapcc 05000ǂaBJ71ǂb.P46 2018 08200ǂa170.9ǂ223 093 ǂa 1001 ǂaPettit, Philip,ǂd1945-ǂeauthor. 24514ǂaThe birth of ethics :ǂbreconstructing the role and nature of morality /ǂcPhilip Pettit ; with commentary by Michael Tomasello ; edited by Kinch Hoekstra. 260 1ǂa[New York, NY] :ǂbOxford University Press,ǂc[2018] 300 ǂavi, 387 pages ;ǂc22 cm 336 ǂatextǂbtxtǂ2rdacontent 337 ǂaunmediatedǂbnǂ2rdamedia 338 ǂavolumeǂbncǂ2rdacarrier 504 ǂaIncludes bibliographical references (pages 359-369) and index. 650 0ǂaEthicsǂxHistory. 7001 ǂaHoekstra, Kinch,ǂeeditor. 906 ǂa7ǂbcbcǂcorignewǂd1ǂeecipǂf20ǂgy-gencatlg 9250 ǂaacquireǂb1 shelf copyǂxpolicy default 955 ǂbrk14 2018-03-21ǂcrk14 2018-03-21 telework to subjǂdrk02 2018-05-11 to Dewey (telework)ǂwxm07 2018-05-11ǂaxn16 2018-12-17 1 copy rec'd., to CIP ver.ǂark20 2018-12-22ǂfrf10 2019-01-17 CIP ver. to CALM 997 ǂa9780190904913|reconstructing the role and nature of morality,The birth of ethics|Hoekstra, Kinch,Pettit, Philip|Oxford University Press,2018ǂhe92a372245c74f5067db151eddd22204ǂv0.03
删除所有的空字段和所有的空子字段如何实现?
dp2内务的种册窗,在MARC编辑器,右键 “整理“-”删除全部空字段”/“删除全部子字段”等一组命令
如何从record中得到指定字段名的MarcField对象? record.select("field[@name='字段名']").firstcontent;强制转换为MarcField好像不行; foreach (MarcField Field in record.Fields) { Field.Name=字段名; } 只能用这种方式吗?
dp2内务的种册窗,在MARC编辑器中,单击“整理”-“删除全部空缺” /“删除全部子替换”等一组命令
MARC编辑器中,此命令是用MarcEdit中的命令完成的。 MarcQuery如何实现呢?
MarcNodeList Fields = record.ChildNodes;
foreach (MarcNode Field in Fields)
{
MarcNodeList SubFields = Field.ChildNodes;
foreach (MarcNode SubField in SubFields)
{
if (string.IsNullOrEmpty(SubField.Content))
{
SubField.detach();
}
}
if (string.IsNullOrEmpty(Field.Content))
{
Field.detach();
}
}
return record;
这样是会报错的,因为foreach中集合已经被更新了
@distinct2010
这样是会报错的,因为foreach中集合已经被更新了
可以这样写:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text;
using System.Xml;
using dp2Circulation;
using DigitalPlatform.Marc;
using DigitalPlatform.Xml;
using DigitalPlatform.Script;
public class MyMarcQueryHost : MarcQueryHost
{
public override void OnRecord(object sender, StatisEventArgs e)
{
var fields = new List<MarcNode>(this.MarcRecord.ChildNodes.List); // 复制到一个新的集合
foreach (var field in fields)
{
var subfields = new List<MarcNode>(field.ChildNodes.List); // 复制到一个新的集合
foreach (MarcNode subfield in subfields)
{
if (string.IsNullOrEmpty(subfield.Content))
{
subfield.detach();
this.Changed = true;
}
}
if (string.IsNullOrEmpty(field.Content))
{
field.detach();
this.Changed = true;
}
}
}
}
上面这个写法,是把 ChildNodes 复制到一个新的集合中(代码中的 fields 或者 subfields),对新的集合进行枚举遍历,就不怕原先的 ChildNodes 在中途被修改了,因为遍历的不是 ChildNodes。