使用 XPath/XQuery 在 SQL 列中创建子节点

发布于 2024-09-19 21:22:24 字数 1123 浏览 8 评论 0原文

我有一个 sql 表,其中有一个名为 CasingRules 的 xml 列,其中包含以下数据:

<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])')

I have a sql table with an xml column named CasingRules, which would contain data such as:

<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>

I'm trying to use MS SQL's modify method to add a new node 'ApplyTo' into each item, to create something like:

<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>

.. but I'm very much a newbie to XPath, and not even sure if its possible to update multiple nodes in one query? Is there an elegant way to achieve this?

I'm expecting the syntax is something like this, but its not working:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

段念尘 2024-09-26 21:22:24

此 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>

This 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(/*)

Output:

<?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>
够钟 2024-09-26 21:22:24

不太确定 MSSQL 中的 XQuery 支持是否可以处理这个问题,但如果有人知道更好的话,我会很高兴听到其他情况(并切换接受的答案)。

所以与此同时,我用 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();
  }
}  

Not so sure XQuery support in MSSQL can handle this, but will be happy to hear otherwise (and switch the accepted answer) if anyone knows better.

So in the meantime, I updated in C# instead:

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();
  }
}  
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文