Использование XPath / XQuery для создания дочерних узлов в столбце SQL - PullRequest
0 голосов
/ 17 сентября 2010

У меня есть таблица sql со столбцом xml с именем CasingRules, который будет содержать такие данные, как:

<root>
  <Item>
    <RegularExpression>^Mc[A-Z,a-z]*</RegularExpression>
    <Format>ULU</Format>
  </Item>
  <Item>
    <RegularExpression>^Mac[A-Z,a-z]*</RegularExpression>
    <Format>ULLU</Format>
  </Item>
</root>

Я пытаюсь использовать метод изменения MS SQL для добавления нового узла ApplyTo вкаждый элемент, чтобы создать что-то вроде:

<root>
  <Item>
    <RegularExpression>^Mc[A-Z,a-z]*</RegularExpression>
    <Format>ULU</Format>
    <ApplyTo>NameAndAddress</ApplyTo>
  </Item>
  <Item>
    <RegularExpression>^Mac[A-Z,a-z]*</RegularExpression>
    <Format>ULLU</Format>
    <ApplyTo>NameAndAddress</ApplyTo>
  </Item>
</root>

.. но я очень новичок в XPath, и даже не уверен, возможно ли обновить несколько узлов в одном запросе?Есть ли элегантный способ добиться этого?

Я ожидаю, что синтаксис примерно такой, но он не работает:

UPDATE TableName
SET CasingRules.modify('insert <ApplyTo>NameAndAddress</ApplyTo> as last into (/root//Item[1])')

Ответы [ 2 ]

0 голосов
/ 20 сентября 2010

Не уверен, что поддержка XQuery в MSSQL справится с этим, но будет рад услышать иное (и переключить принятый ответ), если кто-нибудь узнает лучше.

Итак, пока я обновил в C # вместо этого:

foreach (TypedRow row in typedDataSet)
{
  XmlDocument casingRulesXml = new XmlDocument();
  casingRulesXml.LoadXml(row.CasingRules);

  if (casingRulesXml.GetElementsByTagName("ApplyTo").Count == 0)
  {
    XmlNodeList itemNodes = casingRulesXml.GetElementsByTagName("Item");

    for (int i = 0; i < itemNodes.Count; i++)
    {
      XmlElement newElement = casingRulesXml.CreateElement("ApplyTo");
      newElement.InnerText = "NameAndAddress";
      itemNodes[i].AppendChild(newElement);
    }

    // In this case the xml has no heading declaration.
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.OmitXmlDeclaration = true;
    settings.ConformanceLevel = ConformanceLevel.Fragment;

    StringBuilder stringBuilder = new StringBuilder();
    XmlWriter xmlWriter = XmlWriter.Create(stringBuilder, settings);
    casingRulesXml.WriteTo(xmlWriter);
    xmlWriter.Flush();

    row.CasingRules = stringBuilder.ToString();
  }
}  
0 голосов
/ 17 сентября 2010

Это XQuery:

declare namespace local = "http://example.org";
declare function local:copy($element as element()) {
  element {node-name($element)}
    {$element/@*,
     for $child in $element/node()
        return if ($child instance of element())
          then local:test($child)
          else $child
    }
};
declare function local:test($element as element()) {
  local:copy($element),
  for $true in ($element[parent::Item][not(following-sibling::*)])
  return <ApplyTo>NameAndAddress</ApplyTo>
};
local:copy(/*)

Выход:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <Item>
    <RegularExpression>^Mc[A-Z,a-z]*</RegularExpression>
    <Format>ULU</Format>
    <ApplyTo>NameAndAddress</ApplyTo>
  </Item>
  <Item>
    <RegularExpression>^Mac[A-Z,a-z]*</RegularExpression>
    <Format>ULLU</Format>
    <ApplyTo>NameAndAddress</ApplyTo>
  </Item>
</root>
...