关于字符串解析的问题,有点难度
我要解析一个字符串,例如:string str = "姓名张三性别男出生日期1980年11月19日居住地上海市工作年限一年以上户口上海目前年薪2万以下人民币地址虹口区大连西路500号 ";
我有一个关键字的配置文件
example.xml
<?xml version= "1.0 " encoding= "utf-8 "?>
<root>
<configration EName= "姓名 ">
<Metadata> name </Metadata>
<Metadata> 姓名 </Metadata>
<Metadata> 姓?名 </Metadata>
</configration>
<configration EName= "性别 ">
<Metadata> sex </Metadata>
<Metadata> 性别 </Metadata>
</configration>
<configration EName= "出生日期 ">
<Metadata> 出生日期 </Metadata>
</configration>
<configration EName= "居住地 ">
<Metadata> 居住地 </Metadata>
</configration>
<configration EName= "工作年限 ">
<Metadata> 工作年限 </Metadata>
</configration>
<configration EName= "户口 ">
<Metadata> 户口 </Metadata>
</configration>
<configration EName= "目前年薪 ">
<Metadata> 目前年薪 </Metadata>
</configration>
<configration EName= "地址 ">
<Metadata> 地址 </Metadata>
</configration>
</root>
-------------------------------------------------
我要得到的结果为:
张三
男
1980年11月19日
上海市
一年以上
上海
2万以下人民币
虹口区大连西路500号
--------------------------------------------------
这个字符串是不可知的,关键字也是允许用户配置的,而且这些关键字在字符串里可能存在,也可能不存在,可能存在的形式为: "姓名 ",也可能为: "name ",不管是 "姓名 "还是 "name ",他们同属于一个父节点,因此解析出来的结果是要归结在一起的(可能会同时出现,也可能只出现其中一种).就是说如果是解析中文的时候,遇见 "姓名 "知道后面跟的是名字,英文的话遇见 "name "知道后面是名字.还要一种情况就是关键字的位置是不固定的,可能关键字 "居住地 "在 "性别 "前面,等等,而且关键字要支持通配,比如说 "姓_名 ",就是要匹配开头是姓最后是名中间只允许出现一个的字符串也是关键字,来解析结果.
********************************************************
解决这个问题的朋友,单独开贴送500分.
[解决办法]
这种处理方式不太好。最好是按照一定的格式存储。比如:如果有人姓名为“名XX”的,出来字符串为“姓名名XX”,这样就有多种解释:姓名:名XX 或者 姓名名:XX.
纯属个人意见。
[解决办法]
你的文本字段顺序是按配置文件的吗?
[解决办法]
兄弟把字符串格式搞好,主要点在这,不再于怎么解析.
姓名..性别..生日期..居住地..工作..户口..目前年薪..地址..
如果所有的串都象这种格式那就好办,如果不是....不好办
或者string[]传送
[解决办法]
只要知道要找到节点名字,顺序什么的都无所谓。只需要进行节点遍历即可
[解决办法]
根据配置生成个超大的正则分组获取吧
[解决办法]
你不如说说为什么要这样子做吧
我觉得不必钻牛角尖的,或许有比你这种更好的办法
[解决办法]
如果有重复的关键字,你想解析为什么结果呢?
[解决办法]
呵呵,字符串哪里来的
[解决办法]
用正则表达式匹配即可~
[解决办法]
如果要实现lz的功能,要考虑的情况太多了,难度比较大。
[解决办法]
我感觉还是要从数据源上想办法的
"姓名张三性别男出生日期1980年11月19日居住地上海市工作年限一年以上户口上海目前年薪2万以下人民币地址虹口区大连西路500号 "
这样的字符串处理起来真的很困难,要考虑的情况太多
如果能在取数据源时做些处理,比如说张三和姓名之间加个连字符之类的,应该就可以通过正则来处理了
[解决办法]
//参考如下代码,不太熟悉C#和XML,应该还有优化的地方
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
namespace WindowsApplication8
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
XmlDocument vXmlDocument = new XmlDocument();
vXmlDocument.Load( "C:\\Temp\\example.xml ");
XmlNodeList vXmlNodeList = vXmlDocument.GetElementsByTagName( "configration ");
string str = "姓名张三性别男出生日期1980年11月19日居住地上海市工作年限一年以上户口上海目前年薪2万以下人民币地址虹口区大连西路500号 ";
string vName;
int i;
while (str.Length > 0)
{
vName = null;
foreach (XmlNode vXmlNode in vXmlNodeList)
{
foreach (XmlNode Metadata in vXmlNode.ChildNodes)
{
if (str.IndexOf(Metadata.InnerText) == 0)
{
vName = Metadata.InnerText;
goto loop;
}
}
}
loop: ;
if (vName == null) break;
str = str.Remove(0, vName.Length);
i = str.Length;
foreach (XmlNode vXmlNode in vXmlNodeList)
{
foreach (XmlNode Metadata in vXmlNode.ChildNodes)
{
int j = str.IndexOf(Metadata.InnerText);
if (j > = 0)
i = i < j ? i : j;
}
}
if (i == str.Length)
{
textBox1.Text += str + "\r\n ";
break;
}
else
{
textBox1.Text += str.Remove(i) + "\r\n ";
str = str.Remove(0, i);
}
}
}
}
}
[解决办法]
伴水,Delphi区的牛人,怎么也开始弄C#这种玩具语言了~
[解决办法]
看了下,确实不确定的情况太多,有点麻烦了...
[解决办法]
由于顺序可能不是按照xml文件结点的顺序,所以为方便起见,每次匹配时都是对的全部字符串进行的匹配,这样可能会影响效率,但好在简历一般都不会太长..
如下,目前由于对通配符的说明还不够明确,所以暂时还没写,如果需要,以后可以想办法补上..
初学C#,很多地方还得优化,不过希望能对楼主有所帮助...
class Program
{
static void Main(string[] args)
{
//定义一个列表,用于存储所有关键字
List <string> list = new List <string> ();
XmlDocument doc = new XmlDocument();
doc.Load(@ "../../test.xml ");
XmlNodeList nodes = doc.SelectNodes(@ "//configration ");
//定义一个数组用于存储
KeyWord[] keyWords = new KeyWord[nodes.Count];
int i = 0;
foreach (XmlNode node in nodes)
{
KeyWord key = new KeyWord();
string attri = node.Attributes[ "EName "].Value;
key.EName = attri;
if (!list.Contains(attri))
{
list.Add(attri);
}
foreach (XmlNode childnode in node.ChildNodes)
{
string text = childnode.InnerText;
key.MetaDatas.Add(text);
if (!list.Contains(text))
{
list.Add(text);
}
}
keyWords[i++] = key;
}
//测试字符串
string str = "姓名张三sex男出生日期1980年11月19日居住地上海市工作年限一年以上户口上海目前年薪2万以下人民币地址虹口区大连西路500号 ";
foreach (KeyWord key in keyWords)
{
//起始点
int startIndex = str.IndexOf(key.EName);
//终点
int endIndex = -1;
if (startIndex == -1)
{
//用子关键字进行搜索
foreach (string s in key.MetaDatas)
{
startIndex = str.IndexOf(s);
if (startIndex != -1)
{
startIndex += s.Length;
break;
}
}
}
else
{
startIndex += key.EName.Length;
}
//看通过子关键字进行搜索后是否存在
if (startIndex != -1)
{
//查找终点,即找出离此关键字最近的关键字所在的位置
foreach (string s in list)
{
//先将此关键字及其子关键字从列表中排除
int index = str.Substring(startIndex).IndexOf(s);
if ((endIndex == -1 && index != -1) || (endIndex != -1 && index != -1 && index < endIndex))
{
//替换endIndex
endIndex = index;
}
}
if (endIndex == -1)
{
key.Value = str.Substring(startIndex);
}
else
{
key.Value = str.Substring(startIndex, endIndex);
}
}
}
//测试
foreach (KeyWord key in keyWords)
{
Console.WriteLine(key.EName + ": " + key.Value);
}
}
}
//定义一个参数类
public class KeyWord
{
public string EName = " ";
public List <string> MetaDatas = new List <string> ();
public string Value = " ";
}
------解决方案--------------------
楼主描述不清楚。
楼主给的是
<configration EName= "姓名 ">
<Metadata> name </Metadata>
<Metadata> 姓名 </Metadata>
<Metadata> 姓?名 </Metadata>
</configration>
EName应该就是字段名字,不知道EName要做什么。就是说EName可以是name,姓名,姓?名也作为字段名字?????????
根据这个名字找对应的数据就可以了。
============
我要得到的结果为:?
张三
男
1980年11月19日
上海市
一年以上
上海
2万以下人民币
虹口区大连西路500号
不知道你的这些数据哪来的?什么格式?你的问题里并没有说明。
既然是xml 格式,用xml的类就可以了
[解决办法]
mark
[解决办法]
楼主:我建议你这个字符串有个逗号或什么字符 什么的好一些.你这样也不是实现不了,
只是感觉这样确实有点蠢.
[解决办法]
Mark
[解决办法]
要想做的完全,看看编译原理的词法分析器吧
[解决办法]
mark
[解决办法]
不用这么麻烦吧,叫我想想
^^^^^^^^^^^^^^^^^^^^^^^^^
帮顶之
[解决办法]
既然楼主都做出来了,那我也不用再继续想了...
[解决办法]
string str = "姓名张三性别男出生日期1980年11月19日居住地上海市工作年限一年以上户口上海目前年薪2万以下人民币地址虹口区大连西路500号 ";
//添几个关键字
ArrayList al=new ArrayList();
al.Add( "姓名 ");al.Add( "性别 ");al.Add( "出生日期 ");al.Add( "居住地 ");
al.Add( "工作年限 ");al.Add( "户口 ");al.Add( "目前年薪 ");al.Add( "地址 ");
ArrayList alIndex=new ArrayList();
Hashtable hs=new Hashtable();
for(int i=0;i <al.Count;i++)
{
string strKey=(string)al[i];
int iKeyIndex=str.IndexOf(strKey);
if(iKeyIndex> =0)
{
iKeyIndex+=strKey.Length;
if(!alIndex.Contains(iKeyIndex))
{
alIndex.Add(iKeyIndex);
hs.Add(iKeyIndex,strKey);
}
}
}
alIndex.Sort(null);
int[] iIndexs=(int[])alIndex.ToArray(typeof(int));
ArrayList alResult=new ArrayList();
for(int i=0;i <iIndexs.Length;i++)
{
if(i==iIndexs.Length-1)
alResult.Add(str.Substring(iIndexs[i]));
else
alResult.Add(str.Substring(iIndexs[i],iIndexs[i+1]-iIndexs[i]-hs[iIndexs[i+1]].ToString().Length));
}
//alResult
//有史以来,个人最变态写法之一
[解决办法]
用正则表达式去匹配咯。
另一种思路是,你先找个分词引擎帮你分词,或者你从HTML/Word/Excel格式中获取字符串时先粗略分段。例如在 <table /> 中, " <td> 姓名 </td> <td> 张三 </td> ",这显然是已经帮你分段吧,你不分段就合并起来,然后又要研发自己的智能系统去分段,就多此一举了。