无法在路径中使用 <xsi:type=> 设置 SQL XML 节点级别

Posted

技术标签:

【中文标题】无法在路径中使用 <xsi:type=> 设置 SQL XML 节点级别【英文标题】:Can't set SQL XML node level with <xsi:type=> in path 【发布时间】:2019-12-19 13:43:23 【问题描述】:

我正在尝试使用下面的 SQL 更新语句修改 XML 数据类型字段。我无法设置正确的路径通过级别 /Operand xsi:type="QueryObjectKey"/ 以到达 /Name/ 字段。我可以设置修改/GroupBegin/false/GroupBegin/等父字段/值的路径没有问题,所以我知道SQL语句是正确的,只是到达/Name/的路径语法不对。

我收到这个模棱两可的错误信息

消息 2205,第 16 层,状态 1,第 6 行 XQuery [ACVSCore.Access.Query.XMLEncodedCriteria.modify()]: ")" 是预期的。

如何设置该路径以包含 /Operand xsi:type="QueryObjectKey"/

DECLARE @NewValue Varchar(255) =  'None'

update
[ACVSCore].[Access].[Query]
SET
    XMLEncodedCriteria.modify('replace value of 
    (/QueryExpression/Criteria/CriteriaExpression/Operand xsi:type="QueryObjectKey"/Index/text())[1] with sql:variable("@NewValue")')
<QueryExpression xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" PrimaryObjectType="SoftwareHouse.NextGen.Common.SecurityObjects.Personnel" DataFetcherType="SoftwareHouse.CrossFire.Common.Objects.DataQuery">
  <DataFetcherTag xsi:type="xsd:string" />
  <Criteria>
    <CriteriaExpression>
      <GroupBegin>false</GroupBegin>
      <Operand xsi:type="QueryObjectKey">
        <Name>ORIGINAL</Name>
      </Operand>
    </CriteriaExpression>
  </Criteria>
</QueryExpression>

【问题讨论】:

/QueryExpression/Criteria/CriteriaExpression/Operand xsi:type="QueryObjectKey"/Index/text() 不是有效的 XPath。如果你的意思是说“Operand 节点的属性xsi:type 等于QueryObjectKey”,那就是/QueryExpression/Criteria/CriteriaExpression/Operand[@xsi:type="QueryObjectKey"]/Index/text() 【参考方案1】:

您的 XML 正在使用没有声明的命名空间。首先,您需要修复 XML,然后修改所需的 XML 元素值。 供参考:What is the difference between xsd and xsi?

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xml_data XML);
INSERT INTO @tbl (xml_data) 
VALUES ('<QueryExpression xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 PrimaryObjectType="SoftwareHouse.NextGen.Common.SecurityObjects.Personnel"
                 DataFetcherType="SoftwareHouse.CrossFire.Common.Objects.DataQuery">
    <DataFetcherTag xsi:type="xsd:string"/>
    <Criteria>
        <CriteriaExpression>
            <GroupBegin>false</GroupBegin>
            <Operand xsi:type="QueryObjectKey">
                <Name>ORIGINAL</Name>
            </Operand>
        </CriteriaExpression>
    </Criteria>
</QueryExpression>');
-- DDL and sample data population, end

-- before
SELECT * FROM @tbl;

DECLARE @NewValue VARCHAR(10) = 'None';
UPDATE @tbl
SET xml_data.modify('replace value of 
(/QueryExpression/Criteria/CriteriaExpression/Operand/Name/text())[1] with (sql:variable("@NewValue"))');

-- after
SELECT * FROM @tbl;

【讨论】:

感谢 Yitzhak,感谢您的努力。我按照你的指示做了,但是,@tbl 中 /Name/ 的 ORGINAL 值仍然是它的第一个值,我需要它是 CHANGED 的新值。我错过了什么? ``` DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xml_data XML);插入@tbl (xml_data) 值 ('w3.org/2001/XMLSchema-instance" xmlns:xsd="w3.org/2001/XMLSchema" DataFetcherType="SoftwareHouse.CrossFire.Common.Objects.DataQuery"> ORIGINAL'); ``` ``` 选择 * FROM @tbl;声明 @NewValue VARCHAR(10) = 'CHANGED'; UPDATE @tbl SET xml_data.modify('将 (/QueryExpression/Criteria/CriteriaExpression/Operand/Index/text())[1] 的值替换为 (sql:variable("@NewValue"))') SELECT * FROM @tbl ``` 我根据变更后的要求调整了答案。看看吧。

以上是关于无法在路径中使用 <xsi:type=> 设置 SQL XML 节点级别的主要内容,如果未能解决你的问题,请参考以下文章

从 xml/json JAXB 中删除 xsi:type 信息?

如何定位命名空间 xsi:type="test1"

没有 xsi:type 的 DataContractResolver

Magento 从 mixin 访问 jsLayout 配置数据

使用 xpath 获取 xsi:type 的值 [关闭]

nlog