DigitalPlatform / dp2

Integrated Library System / 图书馆集成系统
http://digitalplatform.github.io/dp2
Apache License 2.0
105 stars 54 forks source link

根据索取号构建架位号 #1173

Open DigitalPlatform opened 1 year ago

DigitalPlatform commented 1 year ago

架位号对照表文件

首先需要一个索取号和架位号的对照表 XML 文件,格式如下:

<root>
  <shelf shelfNo="301B11" accessNoRange="A1/1~A1/18" />
  <shelf shelfNo="301B12" accessNoRange="A1/19~A1/37" />
  <shelf shelfNo="301B13" accessNoRange="A1/38~A1/52" />
   ......

某用户单位提供了一个 Excel 文件的对照表,不过这不是理想的通用格式,为此我们编写了一个转换程序 ConvertShelfNoTable 来负责转换为上述 XML 格式(此 project 在 dp2 solution 中)。

将来可以考虑把 Excel 格式标准化,用户可以用标准化的 Excel 文件提供给我们,然后再编写一个转换到 XML 的 project。

每个馆藏地需要一个对照表 XML 文件,文件名取名为“馆藏地名.xml”(注:若馆藏地名中包含字符 /,需要替换为字符 _)。

为册记录添加 shelfNo 元素

然后需要一个在内务实体查询窗运行的 C# 脚本,负责为册记录添加 shelfNo 元素。代码如下:

// AddShelfNo.cs
// 为册记录添加 shelfNo 元素内容
// 2023/5/20 首次创建代码
// 2023/6/16 增加 DomUtil.RemoveEmptyElements()

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.Xml;
using DigitalPlatform.Text;

/*
 * 要在 .cs 文件所在目录预先准备好若干个 xxx.xml 文件,其中 xxx 代表馆藏地名字,和册记录中的 location 元素内容对应
 * 文件格式如下:
<root>
    <shelf accessNoRange="A11~A22" shelfNo="101A12" />
    <shelf accessNoRange="I712.45/1~I88" shelfNo="777" />
</root> 
 * 每个 shelf 元素,是一个最小划分单位,一般 RFID 盘点情况下是一层
 * */

public class MyItemHost : ItemHost
{
    public override void OnInitial(object sender, StatisEventArgs e)
    {
        if (this.DbType != "item")
        {
            e.Continue = ContinueType.Error;
            e.ParamString = "本程序只能被 实体查询窗 所调用";
            return;
        }
    }
    public override void OnRecord(object sender, StatisEventArgs e)
    {
        string location = DomUtil.GetElementText(this.ItemDom.DocumentElement, "location");
        location = StringUtil.GetPureLocationString(location);
        string accessNo = DomUtil.GetElementText(this.ItemDom.DocumentElement, "accessNo");

        if (string.IsNullOrEmpty(location))
        {
            this.OutputText($"册记录 {this.RecordPath} 馆藏地字段内容为空,无法获得架位号", 2);
            return;
        }
        if (string.IsNullOrEmpty(accessNo))
        {
            this.OutputText($"册记录 {this.RecordPath} 索取号字段内容为空,无法获得架位号", 2);
            return;
        }

        string strDirectory = Path.GetDirectoryName(this.CodeFileName);

        // 通过查找“索取号-架位号”对照文件,用一个索取号获得对应的(理论、永久)架位号
        // parameters:
        //      strDirectory    对照文件所在的目录名。本函数将在这个目录中寻找“馆藏地名.xml”的对照文件
        //      strLocation     馆藏地名。相当于册记录的 location 元素内容的纯净形态
        //      strAccessNo     索取号
        // return:
        //      -1  出错
        //      0   没有找到
        //      1   找到
        var ret = AccessNoUtility.MapShelfNo(
            strDirectory,
            location,
            accessNo,
            out string strShelfNo,
            out string strError);
        if (ret == -1)
        {
            this.OutputText($"册记录 {this.RecordPath} location='{location}' accessNo='{accessNo}' 获得架号时出错: {strError}", 2);
            return;
        }
        if (ret == 0)
        {
            this.OutputText($"册记录 {this.RecordPath} location='{location}' accessNo='{accessNo}' 获得架号时没有找到: {strError}", 2);
            return;
        }

        string old_shelfNo = DomUtil.GetElementText(this.ItemDom.DocumentElement, "shelfNo");
        if (old_shelfNo == strShelfNo)
        {
            // 没有发生变化
            return;
        }
        DomUtil.SetElementText(this.ItemDom.DocumentElement, "shelfNo", strShelfNo);
        // 把 XML 中多余的元素删除
        DomUtil.RemoveEmptyElements(this.ItemDom.DocumentElement);

        this.Changed = true;
    }
}

要在 .cs 文件所在目录预先准备好若干个架位表对照 XML 文件,文件名为 xxx.xml,其中 xxx 代表馆藏地名字(注:若馆藏地名中包含字符 /,需要替换为字符 _),和册记录中的 location 元素内容对应。有多少个馆藏地,就需要准备好多少个架位表对照 XML 文件。

DigitalPlatform commented 1 year ago

校验架位号对照表文件

内务实体查询窗(浏览列表)的上下文菜单里面提供了一个命令和校验架位号对照表文件的正确性。

主要是检查里面用到的索取号范围,互相之间是否发生了重叠。检查有两种模式,一种是严格模式,一种是宽松模式。严格模式下,任意两个范围之间不允许出现任何重叠;宽松模式下,相邻的两个范围之间,如果上一个范围和末尾和下一个范围的开头出现了点状重叠,则不算作重叠,其它情形都算作重叠。

当按住 Ctrl 键触发使用这个校验功能的时候,是宽松模式;否则就是严格模式。

另外,还检查 shelf 元素之间,后面的一个 shelf 元素的索取号范围的起点,应该在前一个 shelf 元素的索取号范围起点的后面。