中國的居民×××編碼格式爲:2位一級行政區代碼;2位二級行政區代碼;2位三級行政區代碼;8位出生日期(年月日);3位識別碼;1位校驗碼。其中校驗碼執行的是×××國家標準GB11643-1999,即ISO7064:1983.MOD 11-2。
前6位的行政區劃代碼包含的信息只能存儲於數據文件中。我看到許多例子都使用數據庫或文本文件對其存儲,查詢起來很不方便。而使用Microsoft.XMLDOM則簡單易行:首先將×××數據轉換爲XML格式,而後經過XPath進尋查詢,體積小,速度快,Client或Server都可執行,也可經過AJAX訪問;而不像數據庫,只能在Server執行。如下是所有JavaScript代碼和XML生成算法的C#代碼。javascript
一、HTML文件:css
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>居民×××編碼合法性檢測(基於客戶端XML數據)</title>
- <style type="text/css">
- body, table {
- font-family:宋體;
- font-size:9pt;
- }
- table, td {
- border-width:1px;
- border-style:solid;
- border-color:#000000;
- }
- td {
- height:30;
- }
- input {
- width:200px;
- height:22px;
- }
- </style>
- <script type="text/javascript" src="CheckChineseID.js"></script>
- <script type="text/javascript">
- function xmlLoad() {
- var xmlDoc = null;
- try {
- if (window.ActiveXObject) //IE
- xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
- else if (document.implementation.createDocument) //Mozilla, Firefox, Opera, etc.
- xmlDoc = document.implementation.createDocument("", "", null);
- xmlDoc.async = false;
- xmlDoc.load("ChineseID.xml");
- xmlDoc.setProperty("SelectionLanguage", "XPath");
- }
- finally {
- return xmlDoc;
- }
- }
- var xmlDoc = xmlLoad();
- function show() {
- if (xmlDoc == null)
- alert(navigator.appName + "不支持XML對象,程序沒法運行!");
- else {
- var result = checkId(id.value, xmlDoc);
- if (typeof result == "string") {
- t0.innerHTML = result;
- t0.style.color = "#FF0000";
- t1.innerHTML = t2.innerHTML = t3.innerHTML = t4.innerHTML = t5.innerHTML = "N/A";
- }
- else {
- t0.innerHTML = "檢測經過!";
- t0.style.color = "#008000";
- t1.innerHTML = result[0];
- t2.innerHTML = result[1];
- t3.innerHTML = result[2];
- t4.innerHTML = result[3] + "年" + result[4] + "月" + result[5] + "日【" + result[6] + "歲】";
- t5.innerHTML = result[7] + "【" + result[8] + "】";
- }
- var blink = 0;
- var blinkId = setInterval(function () {
- blink % 2 == 0 ? t0.style.backgroundColor = "#FFFFC0" : t0.style.backgroundColor = "#FFFFFF";
- if (blink++ == 5) clearInterval(blinkId);
- }, 200);
- }
- }
- </script>
- </head>
- <body>
- <p align="center">
- <small><sub>居民</sub></small>×××編碼合法性檢測(基於客戶端XML數據)<br /><br />
- 白宇 - 夢遼軟件工做室 - 博訊網絡有限責任公司<br />
- Baiyu - Mengliao Software Studio - Bosun Network Co., Ltd.<br />
- 2012.03.02</p>
- <center>
- <table cellpadding="5" cellspacing="0" width="320">
- <tr>
- <td width="100">×××號碼</td>
- <td align="center">
- <input type="text" maxlength="18" id="id" value="請輸入18位×××號碼" style="color:#CCCCCC"
- onfocus="if(this.value=='請輸入18位×××號碼'){this.value='';this.style.color='#000000';}"
- onblur="if(this.value==''){this.value='請輸入18位×××號碼';this.style.color='#CCCCCC';}"
- ondblclick="clipboardData.setData('Text','150722201203020010');alert('示例:150722201203020010\n\n該示例已複製到剪貼板!');"
- onkeypress="if(event.keyCode==13) btn.click()" />
- </td>
- </tr>
- <tr>
- <td>檢測結果</td>
- <td id="t0">N/A</td>
- </tr>
- <tr>
- <td>一級行政區</td>
- <td id="t1">N/A</td>
- </tr>
- <tr>
- <td>二級行政區</td>
- <td id="t2">N/A</td>
- </tr>
- <tr>
- <td>三級行政區</td>
- <td id="t3">N/A</td>
- </tr>
- <tr>
- <td>出生日期</td>
- <td id="t4">N/A</td>
- </tr>
- <tr>
- <td>識別碼</td>
- <td id="t5">N/A</td>
- </tr>
- <tr>
- <td colspan="2" align="center"><input type="button" id="btn" value="檢測" onclick="show()" /></td>
- </tr>
- </table>
- </center>
- </body>
- </html>
二、JavaScript文件:html
- function checkId(id, xmlDoc) {
- var result = new Array();
- var months = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
- if (!id.match(/^\d{17}[\d|x]$/i))
- return "【格式】檢測錯誤!";
- var t = xmlDoc.selectNodes("/China/Province[Code='" + id.substr(0, 2) + "0000']/Name")
- if (t[0] == null)
- return "【一級行政區】檢測錯誤!";
- else
- result.push(t[0].text);
- t = xmlDoc.selectNodes("/China/Province/City[Code='" + id.substr(0, 4) + "00']/Name")
- if (t[0] == null)
- return "【二級行政區】檢測錯誤!";
- else
- result.push(t[0].text);
- t = xmlDoc.selectNodes("/China/Province/City/District[Code='" + id.substr(0, 6) + "']/Name")
- if (t[0] == null)
- return "【三級行政區】檢測錯誤!";
- else
- result.push(t[0].text);
- var y, m, d, now = new Date();
- y = parseInt(id.substr(6, 4));
- m = parseInt(id.substr(10, 2));
- d = parseInt(id.substr(12, 2));
- if (new Date(y + 150, m - 1, d) < now || new Date(y, m - 1, d) > now)
- return "【日期範圍】檢測錯誤!";
- else
- result.push(y);
- if (m < 1 || m > 12)
- return "【月】檢測錯誤!";
- else
- result.push(m);
- if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0)
- months[1] = 29;
- if (d < 1 || d > months[m - 1])
- return "【日】檢測錯誤!";
- else
- result.push(d);
- result.push(now.getFullYear() - y);
- if (id.substr(14, 3) == 0)
- return "【識別碼】檢測錯誤!";
- else {
- result.push(id.substr(14, 3));
- result.push(id.substr(14, 3) % 2 == 0 ? "女" : "男");
- }
- /*
- 校驗碼Hash算法
- ×××國家標準GB11643-1999
- ISO 7064:1983.MOD 11-2校驗碼算法:
- 1) 十七位數字本體碼加權求和公式
- S = Sum(Ai * Wi), i = 0, ... , 16 ,先對前17位數字的權求和
- Ai:表示第i位置上的×××號碼數字值
- Wi:表示第i位置上的加權因子
- Wi:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
- Wi也可表示爲:2^(17 - i) % 11
- 2) 計算模
- Y = mod(S, 11)
- 3) 經過模獲得對應的校驗碼V
- Y:0 1 2 3 4 5 6 7 8 9 10
- V:1 0 X 9 8 7 6 5 4 3 2
- V也可表示爲:mod(12 - Y, 11), 如結果爲10,則轉換爲X
- */
- var Y = 0;
- for (var i = 0; i < 17; i++) {
- var Ai = parseInt(id.substr(i, 1));
- var Wi = Math.pow(2, 17 - i) % 11;
- Y += Ai * Wi;
- }
- Y = (12 - Y % 11) % 11;
- var V = Y == 10 ? "X" : Y.toString();
- if (V != id.substr(17, 1).toUpperCase())
- return "【校驗碼】檢測錯誤!"
- return result;
- }
三、已經轉換好的「行政區劃XML數據」,下載後將其保存爲ChineseID.xml:java
http://mengliao.blog.51cto.com/p_w_upload/201204/876134_1334981976.xml算法
這個XML文件是用C#編寫了一個小程序,對統計局的純文本文件進行轉換,使用了LINQ,核心代碼以下:數據庫
- class Program
- {
- static void Main()
- {
- Console.WriteLine("開始生成XML文件...\n");
- using (StreamReader sr = new StreamReader("行政區劃代碼.txt"))
- {
- int Pid = 0, Cid = 0, Did = 0;
- XElement xe = new XElement("China");
- while (!sr.EndOfStream)
- {
- string[] items = sr.ReadLine().Split(',');
- if (items[0].Substring(2, 4) == "0000") // 後四位爲0,省區級行政區
- {
- xe.Add(new XElement("Province",
- new XAttribute("P.ID", Pid++),
- new XElement("Name", items[1]),
- new XElement("Code", items[0])));
- Cid = 0; // 文件格式中按置省區、市縣、三級行政區依次排列,故沒開始一個新省區行政區,則市縣行政區ID歸0
- Console.Write("生成[{0}]...", items[1]);
- }
- else if (items[0].Substring(4, 2) == "00") // 不然後兩位爲0,市縣級行政區
- {
- var query = (from p in xe.Elements()
- where p.Element("Code").Value.Substring(0, 2) == items[0].Substring(0, 2)
- select p).Single();
- query.Add(new XElement("City",
- new XAttribute("C.ID", Cid++),
- new XElement("Name", items[1]),
- new XElement("Code", items[0])));
- Did = 0; // 文件格式中按置省區、市縣、三級行政區依次排列,故沒開始一個新市縣行政區,則三級行政區ID歸0
- }
- else // 不然後兩位不爲0,三級行政區
- {
- // 分兩步執行查詢,提升性能
- var query = (from p in xe.Elements() // 獲取全部Province元素
- where p.Element("Code").Value.Substring(0, 2) == items[0].Substring(0, 2)
- from c in p.Elements("City") // 獲取該Province元素下的全部City元素
- where c.Element("Code").Value.Substring(2, 2) == items[0].Substring(2, 2)
- select c).Single();
- query.Add(new XElement("District",
- new XAttribute("D.ID", Did++),
- new XElement("Name", items[1]),
- new XElement("Code", items[0])));
- Console.Write(".");
- }
- }
- // 添加註釋,並保存(可使用XElement直接保存)
- XDocument xDoc = new XDocument(new XComment("夢遼軟件2012.03生成"),
- new XComment("×××截至2011.10.31縣及縣以上行政區劃代碼"));
- xDoc.Add(xe);
- xDoc.Save("ChineseID.xml");
- Console.Write("\n\nXML文件成功生成,按任意鍵退出...");
- Console.ReadKey();
- }
- }
- }
以上代碼該有的註釋都有了,就很少解釋了。小程序