2010-04-08 5 views
25

У меня есть документ XML, который выглядит примерно так:Выбрать по нескольким критериям с помощью XPath

<meadinkent> 
<record> 
    <comp_div>MENSWEAR</comp_div> 
    <sty_ret_type>ACCESSORIES</sty_ret_type> 
    <sty_pdt_type>BELTS</sty_pdt_type> 
    <pdt_category>AWESOME_BELTS</pdt_category> 
    </record> 
<medinkent> 

Я хочу useXPath, чтобы выбрать узлы, которые соответствуют все четыре элемента, и у меня возникают проблемы с получением булево синтаксиса права , Я стараюсь, чтобы это совпало с первыми двумя, как тест:

"/meadinkent/record/comp_div[.='" & comp_div & "'] and /meadinkent/record/sty_ret_type[.='" & sty_ret_type & "']" 

Ошибка, если не указано, что ни один узел не возвращается. Очевидно, я очень глуп, что я делаю неправильно?

Приветствие, Мэтта

ответ

42

Союз
Для того, чтобы получить оба узел, нужно использовать накидной оператор - |

Например, следующий запрос будет возвращать оба типа узлов - comp_div и sty_ret_type:

/meadinkent/record/comp_div | /meadinkent/record/sty_ret_type 

Fi фильтр по подузлам значения
Для того, чтобы фильтровать узел на основе его подузлов значения, которые необходимо поместить все условия в том же скобках [nodeA='value1' and nodeB='value2']

Например, следующий запрос возвращает запись узлов, чьи субы узлов сопрягать фильтр:

/meadinkent/record[comp_div='MENSWEAR' and sty_ret_type='ACCESSORIES'] 

переменного тока # объединением пример:

[Test] 
public void UnionExample() 
{ 
    string xml = 
     @"<meadinkent> 
      <record> 
       <comp_div>MENSWEAR</comp_div> 
       <sty_ret_type>ACCESSORIES</sty_ret_type> 
       <sty_pdt_type>BELTS</sty_pdt_type> 
       <pdt_category>AWESOME_BELTS</pdt_category> 
      </record> 
      </meadinkent>"; 

    XDocument xDocument = XDocument.Parse(xml); 
    IEnumerable<XElement> selectedElements = 
     xDocument.XPathSelectElements(
       "/meadinkent/record/comp_div | /meadinkent/record/sty_ret_type"); 

    Assert.That(selectedElements.Count(), Is.EqualTo(2)); 
} 

переменного тока # фильтр, например подузлы:

[Test] 
public void FilterExample() 
{ 
    string xml = 
     @"<meadinkent> 
      <record> 
       <comp_div>MENSWEAR</comp_div> 
       <sty_ret_type>ACCESSORIES</sty_ret_type> 
       <sty_pdt_type>BELTS</sty_pdt_type> 
       <pdt_category>AWESOME_BELTS</pdt_category> 
      </record> 
      </meadinkent>"; 

    XDocument xDocument = XDocument.Parse(xml); 
    IEnumerable<XElement> selectedElements = 
     xDocument.XPathSelectElements(
     "/meadinkent/record[comp_div='MENSWEAR' and sty_ret_type='ACCESSORIES']"); 

    Assert.That(selectedElements.Count(), Is.EqualTo(1)); 
    Assert.That(selectedElements.First().Name.LocalName, Is.EqualTo("record")); 
} 
+0

К сожалению, я не сделал себе ясно. То, что мне нужно, это ссылка на узел Record, который соответствует всем значениям элементов внутри. Поэтому, если я хочу утверждать, что sty_pdt_type - «BELTS», а pdt_category - «AWESOMEBELTS», я хочу ссылку на все узлы записи, для которых эти элементы соответствуют этим значениям. –

+0

@Matt Thrower, я понимаю теперь, что вы имели в виду :) Обновленный ответ соответственно. – Elisha

+0

Удивительно, спасибо! –

6

Вам просто нужно иметь список and ред условий внутри[ ] селектор для record:

/meadinkent/record[compdiv[.='MENSWEAR'] and sty_ret_type[.='ACCESSORIES']] 

Читает как: под верхним уровнем meadinkent узла, в record узел, имеющий ребенка compdiv (со значением MENSWEAR) и ребенок sty_ret_rype (со значением ACCESSORIES).

1

или вы могли бы использовать LINQ для XML и сделать это следующим образом:

var match = XElement.Parse(xmlString); 

var matches = from xml in xmlDocument.Elements() 
       where xml.Element("comp_div").Value == "MENSWEAR" 
       && xml.Element("sty_ret_type").Value == "ACCESSORIES" 
       && xml.Element("sty_pdt_type").Value == "BELTS" 
       && xml.Element("pdt_category").Value == "AWESOME_BELTS" 
       select xml; 
Смежные вопросы