使用XQuery在现有xml节点周围包装节点

时间:2017-08-25 12:16:39

标签: sql-server tsql sql-server-2012 xquery

我有一个包含XML列的大表,其中包含以下格式的历史测验数据:

<quizresult>
  <question>
    <questionText>Which fire extinguisher is most suitable for a waste paper basket fire?</questionText>
    <answer number="0" value="0" chosen="0" imageURL="">Powder</answer>
    <answer number="1" value="0" chosen="0" imageURL="">Carbon Dioxide (CO2)</answer>
    <answer number="2" value="1" chosen="1" imageURL="">Water (H2O)</answer>
    <answer number="3" value="0" chosen="0" imageURL="">Foam</answer>
  </question>
  <question>
    <questionText>What should your immediate action be on hearing a fire alarm?</questionText>
    <answer number="0" value="0" chosen="0" imageURL="">Collect all your valuables</answer>
    <answer number="1" value="0" chosen="0" imageURL="">Check the weather</answer>
    <answer number="2" value="1" chosen="1" imageURL="">Leave the building by the nearest exit, closing doors behind you if the rooms are empty</answer>
  </question>
</quizresult>

是否可以使用TSQL的XQuery在<answers>&gt;周围包裹<answer...个节点。节点?结果将是:

<quizresult>
  <question>
    <questionText>Which fire extinguisher is most suitable for a waste paper basket fire?</questionText>
    <answers>
        <answer number="0" value="0" chosen="0" imageURL="">Powder</answer>
        <answer number="1" value="0" chosen="0" imageURL="">Carbon Dioxide (CO2)</answer>
        <answer number="2" value="1" chosen="1" imageURL="">Water (H2O)</answer>
        <answer number="3" value="0" chosen="0" imageURL="">Foam</answer>
    </answers>
  </question>
  <question>
    <questionText>What should your immediate action be on hearing a fire alarm?</questionText>
    <answers>
        <answer number="0" value="0" chosen="0" imageURL="">Collect all your valuables</answer>
        <answer number="1" value="0" chosen="0" imageURL="">Check the weather</answer>
        <answer number="2" value="1" chosen="1" imageURL="">Leave the building by the nearest exit, closing doors behind you if the rooms are empty</answer>
    </answers>
  </question>
</quizresult>

我已经看到XQuery有一个replace函数,shown here,但是我无法弄清楚如何将答案隔离到函数内部,或者确实如果这是正确的方法

2 个答案:

答案 0 :(得分:1)

除了解构现有的XML并在您想要的结构中重构它之外,我无法看到更简单的方法。 e.g。

DECLARE @T TABLE (ID INT IDENTITY(1, 1), X XML);
INSERT @T (X) VALUES ('<quizresult>
  <question>
    <questionText>Which fire extinguisher is most suitable for a waste paper basket fire?</questionText>
    <answer number="0" value="0" chosen="0" imageURL="">Powder</answer>
    <answer number="1" value="0" chosen="0" imageURL="">Carbon Dioxide (CO2)</answer>
    <answer number="2" value="1" chosen="1" imageURL="">Water (H2O)</answer>
    <answer number="3" value="0" chosen="0" imageURL="">Foam</answer>
  </question>
  <question>
    <questionText>What should your immediate action be on hearing a fire alarm?</questionText>
    <answer number="0" value="0" chosen="0" imageURL="">Collect all your valuables</answer>
    <answer number="1" value="0" chosen="0" imageURL="">Check the weather</answer>
    <answer number="2" value="1" chosen="1" imageURL="">Leave the building by the nearest exit, closing doors behind you if the rooms are empty</answer>
  </question>
</quizresult>');

UPDATE  t
SET     X = (   SELECT  [questionText] = t2.X.value('questionText[1]', 'NVARCHAR(MAX)'),
                        (   SELECT  [@number] = t3.X.value('@number[1]', 'INT'),
                                    [@value] = t3.X.value('@value[1]', 'INT'),
                                    [@chosen] = t3.X.value('@chosen[1]', 'INT'),
                                    [text()] = t3.X.value('text()[1]', 'NVARCHAR(MAX)')
                            FROM    t2.X.nodes('answer') AS t3 (X)
                            FOR XML PATH('answer'), TYPE
                        ) AS answers
                FROM    t.X.nodes('quizresult/question') AS t2 (X)
                FOR XML PATH('question'), ROOT('quizresult')
            ) 
FROM    @T AS t;


SELECT  *
FROM    @t;

将输出:

<quizresult>
  <question>
    <questionText>Which fire extinguisher is most suitable for a waste paper basket fire?</questionText>
    <answers>
      <answer number="0" value="0" chosen="0">Powder</answer>
      <answer number="1" value="0" chosen="0">Carbon Dioxide (CO2)</answer>
      <answer number="2" value="1" chosen="1">Water (H2O)</answer>
      <answer number="3" value="0" chosen="0">Foam</answer>
    </answers>
  </question>
  <question>
    <questionText>What should your immediate action be on hearing a fire alarm?</questionText>
    <answers>
      <answer number="0" value="0" chosen="0">Collect all your valuables</answer>
      <answer number="1" value="0" chosen="0">Check the weather</answer>
      <answer number="2" value="1" chosen="1">Leave the building by the nearest exit, closing doors behind you if the rooms are empty</answer>
    </answers>
  </question>
</quizresult>

答案 1 :(得分:1)

使用XSLT而不是XQuery更容易实现对输入文档的微小更改。在XSLT 3.0中,这是:

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:mode on-no-match="shallow-copy"/>
  <xsl:template match="question">
    <question>
      <xsl:copy-of select="questionText"/>
      <answers>
        <xsl:copy-of select="answer"/>
      </answers>
    </question>
  </xsl:template>
</xsl:transform>

当然,由于数据在SQL Server中,您需要将其导出,转换,然后重新导入,这可能比实际转换花费更长时间(在您的工作量和计算机时间内)。 / p>