【问题标题】:XPath/XQuery - Selecting a node while excluding some elementsXPath/XQuery - 选择一个节点同时排除一些元素
【发布时间】:2012-04-21 05:48:09
【问题描述】:

我有一个需要修改的 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)] }

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

【问题讨论】:

    标签: xml xpath xquery


    【解决方案1】:

    试试这个:

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

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      我喜欢 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>
        

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          猜你喜欢
          • 2019-05-21
          • 2014-06-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多