我需要根据给定的模板从传入(例如xml)数据中提取信息。 模板可以是XML或纯文本(逗号分隔)。对于每种类型的消息,都存在一个模板,例如
<SomeMessage>
<Id>$id</Id>
<Position>
<X>$posX</X>
<Y>$posY</Y>
<Z>$posZ</Z>
</Position>
</SomeMessage>
传入的数据例如是:
<SomeMessage>
<Id>1</Id>
<Position>
<X>0.5f</X>
<Y>1.0f</Y>
<Z>0.0f</Z>
</Position>
</SomeMessage>
现在我需要提取有关$ id,$ posX等的信息。
Parser p = new Parser(templateString);
int id = p.Extract("id", incomingString);
float posx = p.Extract("posX", incomingString);
我需要类似incomingData和模板的不同之处,然后在适当的位置提取信息。因为存在几个包含不同信息的tempaltes,并且将来可以扩展,我正在寻找一种通用的方法。
这种情况下的模板也可能是
$id,$posX,$posY,$posZ
然后输入数据
1,0.5f,1.0f,0.0f
后一种情况可能是解析的问题,但我需要一个能够同时处理的解决方案(xml模板以及非xml)。
答案 0 :(得分:1)
您可以创建一个解析类,其中包含每个字段的属性:
class Parser
{
public string PositionX { get; set; }
public string PositionY { get; set; }
public string PositionZ { get; set; }
public Parser(XmlNode item)
{
this.PositionX = GetNodeValue(item, "Position/X");
this.PositionY = GetNodeValue(item, "Position/X/Y");
this.PositionZ = GetNodeValue(item, "Position/X/Y/Z");
}
}
如果你感兴趣的话,我可以提供一个例程,它可以从sample xml生成这样的解析类。 GetNodeValue是一个使用xpath查询并返回xpath值的方法(基本上是XmlNode.SelectSingleNode,并添加了一些添加的解析)。
答案 1 :(得分:0)
每次使用界面和2个不同的模板可能是个好主意。请注意,返回的消息未完成,但它为您提供了一个想法。使用静态XElement.Parse
,您可以解析格式良好的XML字符串,以便于使用。
public interface IParser
{
Message Parse(String Payload);
}
// Position Class
public class Position
{
public int X { get; private set; }
public int Y { get; private set; }
public int Z { get; private set; }
public Position(int X, int Y, int Z)
{
this.X = X;
this.Y = Y;
this.Z = Z;
}
}
// Message Class
public class Message
{
public String ID { get; private set; }
public Position Position { get; private set; }
public Message(String ID, Position Position)
{
this.ID = ID;
this.Position = Position;
}
}
// Parser Class
public class XMLParser : IParser
{
public Message Parse(string Payload)
{
var result = XElement.Parse(Payload);
return new Message(result.Elements().ElementAt(0).Value, new Position(X,Y,Z);
}
}
答案 2 :(得分:0)
对于每个模板,创建格式为
的解析器定义文件解析器类型(XML或CSV)
Variable1,路径
variable2,path
等
对于xml路径可能是someMessage,Position,x。
对于csv,您可能会忘记路径并按顺序列出变量。
然后,当您读入模板文件时,您将获取解析器类型和每个变量的路径。如果你有很多层次信息,那么你必须对它有一些想象力,但对于你给出的简单案例它应该没问题。
对于任何超过CSV的内容,您可能必须使用解析器,但XML / XPATH很容易找到基础知识。
答案 3 :(得分:0)
using System;
using System.IO;
using System.Xml;
class TemplateParse {
XmlDocument xdoc;
string GetPath(XmlNode node, string val, string path){
if(node.HasChildNodes){
if(node.ChildNodes.Count == 1 && node.FirstChild.NodeType == XmlNodeType.Text)
return (node.FirstChild.Value == val) ? path + "/" + node.Name : String.Empty;
foreach(XmlNode cnode in node.ChildNodes){
if(cnode.NodeType != XmlNodeType.Element) continue;
string result = GetPath(cnode, val, path + "/" + node.Name);
if(result != String.Empty) return result;
}
}
return "";
}
public TemplateParse(string templateXml){
xdoc = new XmlDocument();
xdoc.LoadXml(templateXml);
}
public string Extract(string valName, string data){
string xpath = GetPath((XmlNode)xdoc.DocumentElement, "$" + valName, "/");
var doc = new XmlDocument();
doc.LoadXml(data);
return doc.SelectSingleNode(xpath).InnerText;
// var value = doc.SelectSingleNode(xpath).InnerText;
// var retType = typeof(T);
// return (T)retType.InvokeMember("Parse", System.Reflection.BindingFlags.InvokeMethod, null, null, new []{value});
}
}
class Sample {
static void Main(){
string templateString = File.ReadAllText(@".\template.xml");
string incomingString = File.ReadAllText(@".\data.xml");
var p = new TemplateParse(templateString);
string[] names = new [] { "id", "posX", "posY", "posZ" };
foreach(var name in names){
var value = p.Extract(name, incomingString);
Console.WriteLine("{0}:{1}", name, value);
}
}
}
<强>输出强>
id:1
posX:0.5f
posY:1.0f
posZ:0.0f