XPath/XQuery——选择节点时排除某些元素

3

我有一个XML文件需要修改。首先,我需要按组进行分组,然后排除几个节点。

<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中的“color”和“price”节点。

我试图在返回语句中执行以下操作: { $car[color eq $color]/*[not(self::price)][not(self::color)] }

这种方法有点奏效,但它完全消除了“car”元素!有什么建议吗?

3个回答

6

试试这个:

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

希望这能帮到你。

1

我喜欢Black Sowl的解决方案,但我建议使用稍微更清晰的代码版本。 代码在以下方面更为清晰:

  1. 不需要使用 //cars,因为 cars 是根元素
  2. 第一个 return 语句是不必要的
  3. 不需要重复遍历 cars/car
  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>
    

0
请注意,在XPath中,您无法创建新节点。您只能返回输入文档中已经存在的节点,或者计算诸如计数和总数之类的值,但如果您想要一个新的或修改过的节点树,您需要使用XSLT或XQuery。
如果您的输出与输入相似,只有一些小的变化,那么XSLT解决方案通常比XQuery解决方案简单得多。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接