2012-07-07 38 views
1

我需要C#逻辑来分析XML文件中的某些条件。逻辑应该能够评估的条件,只是告诉我最后的结果是真还是假:编写一个分析XML数据的递归方法

举例:1: 规则(A和B和C)是在XML文件中这样表示:

<Evaluate>  
     <!-- (A AND B AND C)--> 
     <AND>        
      <Condition Name="A" Operator="!=" Value="0"/> 
      <Condition Name="B" Operator="!=" Value="0"/> 
      <Condition Name="C" Operator="==" Value="17"/> 
     </AND>     
    </Evaluate> 

我知道这是简单的事,但下面是一些复杂的规则,从C#代码需要评价: 举例:2:

<Evaluate> 
    <!-- (A AND B) OR C --> 
    <OR> 
     <Condition Name="C" Operator="==" Value="17"/> 
     <AND> 
      <Condition Name="A" Operator="!=" Value="0"/> 
      <Condition Name="B" Operator="!=" Value="0"/> 
     </AND>    
    </OR>     
</Evaluate> 

举例:3:

<Evaluate> 
    <!-- (A) OR ((B AND C) OR D)--> 
    <OR> 
     <Condition Name="A" Operator="!=" Value="0"/> 
     <OR> 
      <Condition Name="D" Operator="!=" Value="0"/> 
      <AND> 
       <Condition Name="B" Operator="!=" Value="0"/> 
       <Condition Name="C" Operator="!=" Value="0"/>      
      </AND> 
     </OR> 
    </OR>    
</Evaluate> 

实施例:4:

<Evaluate> 
    <!-- (A AND B) OR ((C AND D) OR E)--> 
    <OR> 
     <AND> 
      <Condition Name="A" Operator="!=" Value="0"/> 
      <Condition Name="B" Operator="!=" Value="0"/> 
     </AND>    
     <OR> 
      <Condition Name="E" Operator="!=" Value="0"/> 
      <AND> 
       <Condition Name="C" Operator="!=" Value="0"/> 
       <Condition Name="D" Operator="!=" Value="0"/>      
      </AND> 
     </OR> 
    </OR> 
</Evaluate> 

为了解释您关于XML节点:

<Condition Name="D" Operator="!=" Value="0"/>  

意味着,(d!= 0)或没有。

您的帮助,将不胜感激。

+1

有趣的,我不会用递归这个,因为它可能会耗尽内存,如果XML文件太大。你可能需要去编写你自己的解析器;) – GETah 2012-07-07 09:22:44

+1

@GETah:任何大到足以导致问题的文件都必须表示*非常复杂的逻辑。 – 2012-07-07 09:25:02

+3

你已经告诉过我们你想要达到的目标,但是你发现哪一部分很难。你有多远? – 2012-07-07 09:25:51

回答

2

我做了一个样品给你

static void Main(string[] args) 
    { 
     XmlDocument doc = new XmlDocument(); 
     doc.Load("test.xml"); 
     var dict = new Dictionary<string, int>(); 
     dict["A"] = 1; 
     dict["B"] = 0; 
     dict["C"] = 17; 
     var result = Evaluate(doc.FirstChild,dict); 
    } 

    static bool Evaluate(XmlNode node, IDictionary<string, int> dict) 
    { 
     switch (node.Name) 
     { 
      case "Evaluate": 
       return Evaluate(node.FirstChild.NextSibling, dict); // Ignore first comment 
      case "Condition": 
       return Condition(node, dict); 
      case "AND": 
       return And(node, dict); 
      case "OR": 
       return Or(node, dict); 
      default: 
       throw new NotSupportedException(); 
     } 
    } 

    private static bool Or(XmlNode root, IDictionary<string, int> dict) 
    { 
     var result = false; // Starting with false, because It will be true when at least condition is true 
     foreach (XmlNode node in root.ChildNodes) 
     { 
      result |= Evaluate(node, dict); 
     } 
     return result; 
    } 

    private static bool And(XmlNode root, IDictionary<string, int> dict) 
    { 
     var result = true; 
     foreach (XmlNode node in root.ChildNodes) 
     { 
      result &= Evaluate(node, dict); 
     } 
     return result; 
    } 

    private static bool Condition(XmlNode node, IDictionary<string, int> dict) 
    { 
     var name = node.Attributes["Name"].Value; 
     var value = node.Attributes["Value"].Value; 
     var opt = node.Attributes["Operator"].Value; 

     switch (opt) 
     { 
      case "==": 
       return dict[name] == int.Parse(value); 
      case "!=": 
       return dict[name] != int.Parse(value); 
      default: 
       throw new NotSupportedException(); 
     } 
    } 
+0

非常感谢。这完美的作品!但是有一个问题为什么结果在And和Or方法中都设置为true?我在想,如果是的话,结果应该初始化为真,如果是或者结果应该初始化为假。因此,当两个参数是Ored和Anded时,根据第一个参数的结果,应该可以决定And和Or的结果吗?你怎么看?我知道你只是给我一个示例代码。但我想要对优化进行一些说明。 – GanYo 2012-07-08 06:57:08

+0

谢谢,我纠正了OR函数的初始化。 – 2012-07-08 11:06:23

2

也许这样的事情会让你开始。

// warning, not tested 
bool Evaluate(XmlNode node) 
{ 
    // what kind of node is this? call one of the other functions 
} 

bool Condition(XmlNode node) 
{ 
    // this is a condition node, evaluate it 
} 

bool And(XmlNode node) 
{ 
    bool val = true; 
    foreach (XmlNode child in node.ChildNodes) 
    { 
    val = val && Evaluate(child); 
    } 
    return val; 
} 

bool Or(XmlNode node) 
{ 
    bool val = false; 
    foreach (XmlNode child in node.ChildNodes) 
    { 
    val = val || Evaluate(child); 
    } 
    return val; 
} 
+0

好方法,这也很完美。 – GanYo 2012-07-08 06:58:07