从文本模板中解析/提取信息

时间:2011-11-30 12:35:19

标签: c# parsing templates

我需要根据给定的模板从传入(例如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)。

4 个答案:

答案 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