Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPath/XQuery - Selecting a node while excluding some elements

Tags:

xml

xpath

xquery

I have an XML file which I need to modify. First I need to do a group by and then exclude a couple of nodes.

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

Here is my code that does the transformation:

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

I get:

<?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>

This does 95% of what I need except for one problem. I need to exclude nodes "color" and "price" from the final XML while preserving the grouping.

I tried to do the following in my return statement: { $car[color eq $color ]/*[not(self::price)][not(self::color)] }

sort of works but it completely eliminates the "car" element!! Any advice?

like image 825
Stan C Avatar asked Oct 19 '25 19:10

Stan C


1 Answers

Try this:

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

Hope this helps.

like image 172
black sowl Avatar answered Oct 26 '25 12:10

black sowl