非常复杂的XQuery转换

非常复杂的XQuery转换,xquery,Xquery,我要编写一个非常复杂的XQuery(至少按照我的标准) 以下是我的输入xml: <testRequest> <request1> <Line>1</Line> <action>addtoName</action> </request1> <request2> <Line>2</Line> <

我要编写一个非常复杂的XQuery(至少按照我的标准)

以下是我的输入xml:

<testRequest>
    <request1>
       <Line>1</Line>
       <action>addtoName</action>
    </request1>
    <request2>
        <Line>2</Line>
        <action>addtoSpace</action>
    </request2>
    <request3>
         <Line>3<Line>
         <action>addtospace</action>
    </request3>
</testRequest>

1.
addtoName
2.
附加空间
3.
附加空间
在我的输出xml中,动作应该作为属性附加到“request1”元素。因此,基于request1元素下的action元素,request1元素的属性应该是以下之一:

if action = IgnoreCase(addtoName), the request1 element should be <request1 action=insertingname>
if action =  IgnoreCase(addtoSpace), the request1 element should be <request1 action=updatingspace>
如果action=IgnoreCase(addtoName),则request1元素应为
如果action=IgnoreCase(addtoSpace),则request1元素应为
不仅如此,我还需要根据元素下面的动作值向元素添加一个属性。 因此,我必须遍历元素下的每个元素,看看是否有任何元素等于“addtospace”。如果是,那么我需要得到元素的相应值,并组成元素的属性。根据上面的xml,元素的属性应该是

<testRequest lineFiller="Line Like 2_* AND Line Like 3_*>, where 2 and 3 are the respective line numbers.

1.
addtoName
2.
附加空间
3.
附加空间
任何帮助完成这项艰巨任务的人都将不胜感激


谢谢

您应该定义函数来生成需要添加到元素中的属性

要添加到“request”元素,应该可以:

declare function local:getaction($x) {
  if (lower-case($x/action) = "addtoname") then attribute action {"insertingspace"} else
  if (lower-case($x/action) = "addtospace") then attribute action {"updatingspace"} else
  ()
};
可以类似地创建“linefiller”属性:

declare function local:getfiller($x) {
  attribute lineFiller {
      if ($x/*[lower-case(action) = "addtospace"]) then
          string-join(
          for $r in $x/*[lower-case(action) = "addtospace"]
            return concat("Line Like ",$r/Line,"_*")
          , " AND ")
      else "change"
      }
};
然后,为了将它们放在一起,在原始文档上创建一个简单的for循环,在需要的地方添加属性:

let $doc:=<<your original document>>

return
<testRequest>
{ local:getfiller($doc) }
{ for $r in $doc/* return 
   element { name($r) } { 
    local:getaction($r),
    $r/* 
   }
}
</testRequest>
let$doc:=
返回
{local:getfiller($doc)}
{对于$doc中的$r/*返回
元素{name($r)}{
本地:getaction($r),
$r/*
}
}

编辑:增强的getfiller函数,如果没有操作,则返回“更改”

您应该定义函数以生成需要添加到元素中的属性

要添加到“request”元素,应该可以:

declare function local:getaction($x) {
  if (lower-case($x/action) = "addtoname") then attribute action {"insertingspace"} else
  if (lower-case($x/action) = "addtospace") then attribute action {"updatingspace"} else
  ()
};
可以类似地创建“linefiller”属性:

declare function local:getfiller($x) {
  attribute lineFiller {
      if ($x/*[lower-case(action) = "addtospace"]) then
          string-join(
          for $r in $x/*[lower-case(action) = "addtospace"]
            return concat("Line Like ",$r/Line,"_*")
          , " AND ")
      else "change"
      }
};
然后,为了将它们放在一起,在原始文档上创建一个简单的for循环,在需要的地方添加属性:

let $doc:=<<your original document>>

return
<testRequest>
{ local:getfiller($doc) }
{ for $r in $doc/* return 
   element { name($r) } { 
    local:getaction($r),
    $r/* 
   }
}
</testRequest>
let$doc:=
返回
{local:getfiller($doc)}
{对于$doc中的$r/*返回
元素{name($r)}{
本地:getaction($r),
$r/*
}
}

编辑:增强的getfiller函数,在没有操作时返回“change”

Hi evil otto,首先,非常感谢您提供的解决方案。。。它起了部分作用。不起作用的零件是填充线零件。函数似乎总是返回空字符串。此外,如果没有名为“Addtospace”的元素,函数应该返回“Changed”。我现在被难住了。无论如何,非常感谢你的帮助!你真了不起!我更新了
getfiller
函数,以便在没有操作时放入字符串。我不知道为什么函数不应该返回一些东西;我从我的工作测试代码中逐字复制了它。你用的是什么xquery引擎?再次感谢你,邪恶的奥托!这个解决方案实际上奏效了。。。昨天是我的错。。。我做了些蠢事。我还有最后一个请求。如果我想修改getfiller函数来测试“addtospace”和“addtoline”,并在这两种情况下执行相同的操作,我该怎么做?我已经厌倦了这样做:在$x/*[小写字母(action)=“addtospace”或“addtoline”]中为$r添加相同的内容,并在if语句中添加了相同的内容,但这不起作用。您有两个选择:
小写字母(action)=“addtospace”或小写字母(action)=“addtoline”
小写字母(action)=(“addtospace”,“addtoline”)
——后者对于这种特殊情况更为简洁,但前者更为一般(分离出或子条件)。嗨,邪恶的奥托,首先,非常感谢你的解决方案。。。它起了部分作用。不起作用的零件是填充线零件。函数似乎总是返回空字符串。此外,如果没有名为“Addtospace”的元素,函数应该返回“Changed”。我现在被难住了。无论如何,非常感谢你的帮助!你真了不起!我更新了
getfiller
函数,以便在没有操作时放入字符串。我不知道为什么函数不应该返回一些东西;我从我的工作测试代码中逐字复制了它。你用的是什么xquery引擎?再次感谢你,邪恶的奥托!这个解决方案实际上奏效了。。。昨天是我的错。。。我做了些蠢事。我还有最后一个请求。如果我想修改getfiller函数来测试“addtospace”和“addtoline”,并在这两种情况下执行相同的操作,我该怎么做?我已经厌倦了这样做:在$x/*[小写字母(action)=“addtospace”或“addtoline”]中为$r添加相同的内容,并在if语句中添加了相同的内容,但这不起作用。您有两个选择:
小写字母(action)=“addtospace”或小写字母(action)=“addtoline”
小写字母(action)=(“addtospace”,“addtoline”)
——对于这种特殊情况,后者更为简洁,但前者更为通用(分离出或子条件)ridermule,使用XSLT进行此类处理要容易得多。您对XSLT解决方案感兴趣吗?Dimitre,我实际上非常精通XSLT。。。但不幸的是,上周有人(当然不是我)呼吁我们应该只使用XQuery而不是XSLT。所以,我现在正在学习XQuery。ridermule,我很同情你。也许是时候换一份工作了?:)我希望在一个小城市里找到一份新工作这么容易!:)ridermule,使用XSLT进行此类处理要容易得多。您对XSLT解决方案感兴趣吗?Dimitre,我实际上非常精通XSLT。。。但不幸的是,上周有人(当然不是我)呼吁我们应该只使用XQuery而不是XSLT。所以,我现在正在学习XQuery。ridermule,我很同情你。也许是时候换一份工作了?:)我希望能找到一份新工作