【问题标题】:Can xquery delete the text xmlns="" from a nodexquery 可以从节点中删除文本 xmlns=""
【发布时间】:2017-07-14 15:53:13
【问题描述】:

操作系统:Windows 10

MS SQL 版本:SQL 2016

我对 StackOverflow 进行了广泛的搜索,发现了许多与我的问题非常相似的问题,但似乎没有一个问题与我的情况相匹配,或者没有一个我有知识或技能可以实施的回答。我不知道如何在 SQL 中实现 C# 解决方案,也不知道如何使用样式表转换语言,所以这是我的问题。

我正在从一个表创建一个 XML 文档,并且它必须与我客户的布局完全匹配。文档的外部结构如下所示:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <ScreenResponse xmlns="http://schemas.myuri.com/CC/v1_4">
      <CustomerScreenResult>
       <ServiceCallID />
        <IsSuccessful>true</IsSuccessful>
        <CustomerScreenResponse>
          <IsSuccessful>true</IsSuccessful>
        </CustomerScreenResponse>
      </CustomerScreenResult>
    </ScreenResponse>
  </s:Body>
</s:Envelope>

上面的对象在我的存储过程中称为@xml_out,具有XML 数据类型,并且保持不变。请注意,它只使用模式和命名空间,没有样式表。接下来,我构建了另一个 XML 文档,它只显示客户需要查看的节点。它看起来像这样:

<SpecificScreenResults>
  <CaseScreenResult>
    <ScreenMessage>This is a sample screenmessage.</ScreenMessage>
  </CaseScreenResult>
  <CaseScreenResult>
    <ScreenMessage>This is another sample screenmessage.</ScreenMessage>
  </CaseScreenResult>
</SpecificScreenResults>

在 SSMS 中,我使用与此类似的代码创建该文档:

SET @xml_var1 = ( SELECT a.ScreenMessage
FROM #CustScrn a 
FOR
XML PATH('CaseScreenResult'),
ELEMENTS,
ROOT ('SpecificScreenResults'),
TYPE);

最后,我使用 xquery insert 语句将第二个 XML 对象 (@xml_var1) 插入到第一个 XML 对象中。首先,这是我使用的 SQL 语句:

SET @xml_out.modify('declare default element namespace "http://schemas.myuri.com/CC/v1_4"; insert sql:variable ("@xml_var1") as first into (//CustomerScreenResponse)[1]');

这会产生以下 XML 对象:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <ScreenResponse xmlns="http://schemas.myuri.com/CC/v1_4">
      <CustomerScreenResult>
        <ServiceCallID />
        <IsSuccessful>true</IsSuccessful>
        <CustomerScreenResponse>
          <SpecificScreenResults xmlns="">
            <CaseScreenResult>
              <ScreenMessage>This is a sample screenmessage.</ScreenMessage>
            </CaseScreenResult>
            <CaseScreenResult>
              <ScreenMessage>This is another sample creenmessage.</ScreenMessage>
            </CaseScreenResult>
          </SpecificScreenResults>
          <IsSuccessful>true</IsSuccessful>
        </CustomerScreenResponse>
      </CustomerScreenResult>
    </ScreenResponse>
  </s:Body>
</s:Envelope>

注意一个节点,SpecificScreenResults 正在接收额外的 xmlns="" 命名空间指示。我认为这是因为我插入的 XML 没有与命名空间相关联,因此添加了一个空白。我知道,从 XML 的角度来看,这个文本是微不足道的,但对我的客户来说,这是他们不想处理的烦恼。目前我处理问题的方式是将整个对象转换为 VARCHAR(MAX),使用 REPLACE() 函数将其删除,然后将其转换回 XML。这适用于有几条记录的结果,但当表结果数以百万计时,效果就不太好了。

是或否,我可以使用 xquery delete 命令从节点中删除 xmlns="" 吗?有没有更好的方法来执行插入以防止出现空白?如果是这样,有人可以提供一个例子吗?

【问题讨论】:

    标签: sql-server xml


    【解决方案1】:

    这个xmlns="" 不仅烦人,它还指定内部节点不存在于您在上面声明的默认命名空间中! 这很可能,实际上不是您想要的。 .

    您可以创建要插入的节点,包括WITH XMLNAMESPACES(...)。这将在与外部节点相同的默认命名空间内创建新节点。通过.modify() 插入后,您会注意到,您会多次找到您的xmlns="..."。这没有错,只是让您的 XML 变得烦人和臃肿......

    这是一个长期存在的问题。看到这个Connect article!请登录并投票!

    字符串方法有几种方法。丑陋,但工作......

    目前我处理此问题的方式是将整个对象转换为 VARCHAR(MAX),使用 REPLACE() 函数将其删除,然后将其转换回 XML。

    这没关系,但您应该使用NVARCHAR。使用 VARCHAR 可能会让您遇到 non-plain-latin 字符的麻烦...

    大多数人会建议在没有任何命名空间的情况下创建 XML,并在末尾使用 STUFF 在字符串级别插入所有命名空间。

    【讨论】:

      【解决方案2】:

      我知道从 XML 的角度来看,这个文本是微不足道的, 但对我的客户来说,他们不想交易是一件令人恼火的事 与。

      相反,这个小小的声明非常重要。

      您在没有命名空间的情况下创建了 &lt;SpecificScreenResults&gt; 元素及其后代。当您将其复制为另一个文档的子树时,它不会保留在任何命名空间中,并且添加了 xmlns="" 声明以反映这一事实。

      您似乎希望&lt;SpecificScreenResults&gt; 元素位于命名空间"http://schemas.myuri.com/CC/v1_4" 中。如果您希望在该命名空间中使用它,则必须在该命名空间中创建它,或者随后对其进行转换以更改其命名空间。

      重要的是要记住元素的名称是 (namespace, local-name) 对,当你复制一个元素时,它的名称保持不变。像xmlns="" 这样的命名空间声明不是 XPath/XQuery 数据模型的一部分,它们是词法(序列化)XML 的产物,旨在确保当您将树转换为词法 XML 然后将其解析回树时,元素的名称保持不变。如果一个元素是一个命名空间,而其父元素在不同的命名空间中,那么在序列化时,将添加命名空间声明以反映这一事实。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-13
        • 1970-01-01
        • 2015-07-31
        • 1970-01-01
        • 2012-08-15
        相关资源
        最近更新 更多