2012-04-21 2 views
3

У меня есть XML-файл, который мне нужно изменить. Сначала мне нужно сделать группу, а затем исключить пару узлов.XPath/XQuery - выбор узла, исключая некоторые элементы

<cars> 
    <car> 
     <make>Toyota</make> 
     <model>Camry</model> 
     <color>White</color> 
     <price>123</price> 
    </car> 
    <car> 
     <make>Honda</make> 
     <model>Accord</model> 
     <color>White</color> 
     <price>423</price> 
    </car> 
</cars> 

Вот мой код, который делает преобразование:

<root> 
    { 
    for $color in distinct-values(doc('cars.xml')//cars/car/color) 
    let $car := doc('cars.xml')//cars/car 
    return <appearance color="{$color}"> 
      { $car[color eq $color ] } 
      </appearance> 
    } 
</root> 

я получаю:

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <appearance color="White"> 
     <car> 
      <make>Toyota</make> 
      <model>Camry</model> 
      <color>White</color> 
      <price>123</price> 
     </car> 
     <car> 
      <make>Honda</make> 
      <model>Accord</model> 
      <color>White</color> 
      <price>423</price> 
     </car> 
    </appearance> 
</root> 

Это делает 95% того, что мне нужно для одной задачи, за исключением. Мне нужно исключить узлы «цвет» и «цена» из окончательного XML, сохраняя при этом группировку.

я попытался сделать следующее в моем возвращении заявлении: {$ автомобиля [цвет эк $ цвета]/* [не (само :: цена)] [не (сам :: цвета)]}

вроде работ, но он полностью исключает элемент «автомобиль»! Любой совет?

ответ

5

Попробуйте это:

<root> 
{ 
    let $cars-doc := doc('cars.xml') 
    let $color := distinct-values($cars-doc//cars/car/color) 
    return 
     for $carcolor in $color 
     return 
      <appearance color="{$carcolor}"> 
      { 
       for $car in $cars-doc//cars/car 
       where $car/color = $carcolor 
       return 
        <car> 
        {$car/*[not(self::color or self::price)]} 
        </car> 
      } 
      </appearance> 
} 
</root> 

Надеется, что это помогает.

0

Обратите внимание, что в XPath вы не можете создавать новые узлы. Вы можете либо вернуть узлы, которые уже существуют во входном документе, без изменений, либо вы можете вычислить такие значения, как подсчеты и итоговые значения, но если вы хотите новое или измененное дерево узлов, вам нужны XSLT или XQuery.

Если ваш выход будет похож на ваш вход с небольшими изменениями, то решение XSLT часто намного проще, чем решение XQuery.

1

Мне нравится решение для черных sowl, но я бы предложил следующую немного более чистую версию кода. Уборщик этими способами:

  1. Нет необходимости использовать // автомобили, поскольку автомобили является корневым элементом
  2. 1-оператор возврата ненужный
  3. Нет необходимости повторно траверсы автомобилей/автомобиль
  4. Использование единственного числа & множественного числа в именах переменных, чтобы указать один элемент по сравнению с последовательностью

    <root> 
        { 
        let $cars := doc('cars.xml')//car 
        let $colors := distinct-values($cars/color) 
        for $color in $colors 
        return 
         <appearance color="{$color}"> 
          { 
          for $car in $cars[color = $color] 
          return 
           <car> 
            {$car/*[not(self::color or self::price)]} 
           </car> 
          } 
         </appearance> 
        } 
    </root> 
    
Смежные вопросы