我有一个我需要修改的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中排除节点“颜色”和“价格”,同时保留分组。
我尝试在return语句中执行以下操作: {$ car [color eq $ color] / * [not(self :: price)] [not(self :: color)]}
有点工作,但它完全消除了“汽车”元素!有什么建议吗?
答案 0 :(得分: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>
希望这有帮助。
答案 1 :(得分:1)
我喜欢black sowl的解决方案,但我建议使用以下稍微清洁的代码版本。通过以下方式清洁:
使用单数和&amp;变量名中的复数表示单项与序列
<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>
答案 2 :(得分:0)
请注意,在XPath中,您无法创建新节点。您可以返回输入文档中已存在的节点,也可以计算计数和总计等值,但如果需要新的或修改过的节点树,则需要XSLT或XQuery。
如果您的输出与您的输入类似,只需进行少量更改,那么XSLT解决方案通常比XQuery解决方案简单得多。