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 中排除节点“颜色”和“价格”,同时保留分组。

我尝试在我的退货声明中执行以下操作: { $car[color eq $color ]/*[not(self::price)][not(self::color)] }

有点作品,但它完全消除了“汽车”元素!有什么建议吗?

4

3 回答 3

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>  

希望这可以帮助。

于 2012-04-21T06:19:51.100 回答
1

我喜欢 black sowl 的解决方案,但我建议使用以下稍微干净一点的代码版本。通过这些方式清洁:

  1. 不需要使用 //cars 因为汽车是根元素
  2. 不需要第一个 return 语句
  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>
    
于 2012-04-21T22:03:34.927 回答
0

请注意,在 XPath 中,您不能创建新节点。您可以原封不动地返回输入文档中已经存在的节点,也可以计算诸如计数和总数之类的值,但是如果您想要一个新的或修改过的节点树,则需要 XSLT 或 XQuery。

如果您的输出将与您的输入相似,只是稍作改动,那么 XSLT 解决方案通常比 XQuery 解决方案简单得多。

于 2012-04-21T16:56:05.277 回答