在中级xquery按元素local-name排序xml

时间:2014-10-09 13:35:04

标签: sql xml sql-server-2008-r2 xquery flwor

我想通过元素的名称在某个级别重新排序某些xml的所有元素,但是我遇到了一些麻烦。这是我正在使用的一个示例xml输出(我在SQL Server 2008 R2的变量@XML中使用它:

<Data>
  <Uns>
    <Orgs>
      <Prods>
        <Prod>
          <Something>1</Something>
          <Cars>
            <Car>
              <Number>2013213</Number>
              <BasicInfo>
                <FirstName>Bob</FirstName>
                <LastName>Monkhouse</LastName>
              </BasicInfo>
              <Anything>654</Anything>
            </Car>
            <Car>
              <Number>2013213</Number>
              <BasicInfo>
                <FirstName>Bob</FirstName>
                <LastName>Monkhouse</LastName>
              </BasicInfo>
              <Anything>654</Anything>
            </Car>
          </Cars>
        </Prod>
        <Prod>
          <Cars>
            <Car>
              <Number>2013213</Number>
              <BasicInfo>
                <FirstName>Bob</FirstName>
                <LastName>Monkhouse</LastName>
              </BasicInfo>
              <Anything>654</Anything>
            </Car>
          </Cars>
        </Prod>
       </Prods>
    </Orgs>
  </Uns>
</Data>

我想按字母顺序修改<Cars>的所有子元素的顺序(在上例中),保持其内容不变。继另一个question的帮助之后,答案提出了想法,但是出现了错误,我已经完全扭转了尝试各种各样的变化:

select @XML.query('element Cars {
  for $anything in //Car
  order by local-name($anything/*[1])
  return $anything
}')

但似乎没有任何效果。我发现我经常遇到这三个问题的组合:一个错误,表示&#34; XQuery语法&#39; / function()&#39;不支持&#34;,丢失所有父元素(如上例所示)或者根本没有发生任何事情(如上所述)。我担心我应该使用SET @XML.modify()代替SELECT @XML.query(),但这会导致更少的结果。

我在互联网上进行了大量的拖网,但我找到的所有网站似乎都没有对xquery FLWOR语法有一个非常全面的了解 - 只是给出了具体而且通常很简单的例子,这些都没有帮助我找到解决方案,为什么这不符合我的期望。

以下是转换后上面的xml理想情况(Number,BasicInfo和Anything的顺序改为字母顺序):

<Data>
  <Uns>
    <Orgs>
      <Prods>
        <Prod>
            <Something>1</Something>
          <Cars>
            <Car>
              <Anything>654</Anything>
              <BasicInfo>
                <Name>Bob</Name>
              </BasicInfo>
              <Number>2013213</Number>
            </Car>
            <Car>
              <Anything>654</Anything>
              <BasicInfo>
                <Name>Bob</Name>
              </BasicInfo>
              <Number>2013213</Number>
            </Car>
          </Cars>
        </Prod>
        <Prod>
          <Cars>
            <Car>
              <Anything>654</Anything>
              <BasicInfo>
                <Name>Bob</Name>
              </BasicInfo>
              <Number>2013213</Number>
            </Car>
          </Cars>
        </Prod>
       </Prods>
    </Orgs>
  </Uns>
</Data>

非常感谢任何帮助和建议;我将继续在线搜索,以便更全面地了解语法及其正在做什么,但在此阶段获得某种结果将是一个真正的提升!

谢谢!

1 个答案:

答案 0 :(得分:1)

您想要对每个<Car/>元素中的元素重新排序,因此需要两个for循环。以下应该有效:

for $car in //Car
return <Car>{
  for $el in $car/*
  order by local-name($el)
  return $el
}</Car>

您将不得不重建父元素,因为XQuery无法修改现有节点(您可能需要XQuery更新,我非常怀疑SQL Server 2008是否支持)。

但是,请注意,我很难想象您的重新订购可能会用于什么。它代表与以前完全相同的信息,每个XML解析器都不应该有所作为。我从未见过有人想简单地重新排序节点,通常它会针对节点的相同值进行(例如重新排序元素,因此最昂贵的节点是第一个)。