Просто некромантия, поскольку появился XPath 2.0.
С XPath 2.0 вы можете:
/Location/Addr[State=('TX', 'AL', 'MA')]
Кроме того, с XPath 1.0 вы можете использовать contains в сочетании с длиной строки:
DECLARE @tXML xml = '<svg>
<g>
<path></path>
<path data-objid="0000X1">tt</path>
<path data-objid="0000X2"></path>
<path data-objid="0000X3"></path>
</g>
</svg>';
-- SELECT @tXML;
SELECT
c.p.value('(@data-objid)[1]', 'varchar(50)') AS objID
FROM @tXML.nodes('//node()[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]') AS c(p)
SET @tXML.modify('delete //node()[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]');
SELECT @tXML AS del;
DECLARE @newRecord xml = '<path data-objid="0000X4"></path>';
-- SET @tXML.modify('insert sql:variable("@newRecord") as first into (/svg/g)[1]')
SET @tXML.modify('insert sql:variable("@newRecord") as last into (/svg/g)[1]')
SELECT @tXML AS ins;
См. также: добавить блок в определенную позицию
И для обновления (с xml вы можете обновлять только одно значение за раз, а селектор text() ничего не находит для пустого элемента, поэтому вам сначала нужно очистить элемент, затем вставить значение, и так для каждого совпадения) :
SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/text())[1] with "40"')
SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/text())[2] with "40"')
SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/text())[1] with ""')
SET @tXML.modify('insert text{"This Works"} into (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])[1]')
SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/text())[2] with ""')
SET @tXML.modify('insert text{"This Works"} into (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])[2]')
И вставить и удалить атрибут
-- insert attribute
-- SET @tXML.modify('insert attribute data-objid1 {"1"} into (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])[1]')
-- delete attribute
-- and then, delete suddenly can remove several nodes - unlike insert or modify ...
-- SET @tXML.modify('delete (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])/@data-objid[1]')
-- only insert if there is no attribute "data-objid", therefore check with [not(@data-objid)]
-- (on replace, it doesn't create an attribute if it doesn't exist)
SET @tXML.modify('insert attribute data-objid {"1"} into (//path[not(@data-objid) and contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])[1]')
SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/@data-objid)[1] with "Test"')
И с переменными:
DECLARE @testvar varchar(30);
SET @testvar = 'abc';
SET @tXML.modify('insert attribute data-objid {sql:variable("@testvar")} into (//path[not(@data-objid)] and contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0)[1]')
SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/@data-objid)[1] with sql:variable("@testvar")')
SET @testvar = '0000X1,0000X2';
SET @tXML.modify('delete (//path[contains(sql:variable("@testvar"), @data-objid) and string-length(@data-objid) != 0])/@data-objid[1]')
Обратите внимание, что вы должны объединить атрибут data-objid
с ("," + objid + ",")
, чтобы модификация случайно не нашла его, если тестовая переменная ',0000X1a,0000X2b,'
вместо ',0000X1,0000X2,'
(например)
DECLARE @testvar varchar(30);
SET @testvar = ',0000X1a,0000X2b,';
SET @tXML.modify('delete (//path[contains(sql:variable("@testvar"), concat(",", @data-objid, ",")) and string-length(@data-objid) != 0])/@data-objid[1]')
SELECT @tXML
person
Stefan Steiger
schedule
07.07.2017