T-SQL 查找具有匹配文本的节点并从 XML 字段中的兄弟节点中提取值
T-SQL Find node with matching text and extract value from sibling node in XML field
我有一个 table,其中 xml 字段的内容如下:
<ContentBlock xmlns="http://corp.com/wdpr/ContentBlock">
<key xlink:href="tcm:0-133036" xlink:title="entityCard" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<template xlink:href="tcm:0-132970" xlink:title="card-header-read-more-all-media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<section>
<name xlink:href="tcm:0-132988" xlink:title="header" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Make a Friend</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-133110" xlink:title="readMore" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals at the only petting zoo in Disney’s Animal
Kingdom park.
</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-132939" xlink:title="readAll" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals.
</p>
<p xmlns="http://www.w3.org/1999/xhtml">Pet, brush and feed domesticated creatures
</p>
<ul xmlns="http://www.w3.org/1999/xhtml">
<li xmlns="http://www.w3.org/1999/xhtml">Goats</li>
</ul>
<p xmlns="http://www.w3.org/1999/xhtml">Handy animal brushes are available .
</p>
<p xmlns="http://www.w3.org/1999/xhtml">
<strong xmlns="http://www.w3.org/1999/xhtml">Keeping Clean</strong>
<br xmlns="http://www.w3.org/1999/xhtml"/>Guests are encouraged to cleanse.</p>
</content>
</section>
<media>
<name xlink:href="tcm:0-201994" xlink:title="media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<key xlink:href="tcm:0-132952" xlink:title="170 x 96" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<image xlink:href="tcm:0-231377" xlink:title="section-01.jpg" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
</media>
</ContentBlock>
我的目标是有一个查询,我可以在其中找到(例如)包含文本 "Make a Friend" 的 <p>
,然后获取 [=15= 的 xlink:href ] 元素在同一个 <section>
标签中。
我尝试了以下帖子中的几个选项:here and 但我没有得到我需要的结果。
这行不通
SELECT a.value1,
x.XmlCol.value('(section/content/p)[1]','VARCHAR(100)') AS SendMethod
FROM @test a
CROSS APPLY a.AppConfig.nodes('/ContentBlock') x(XmlCol)
WHERE x.XmlCol.exist('section/content/p[contains(.,"Make a Friend")]') = 1
如何获取?
提前致谢。吉列尔莫.
这样试试:
DECLARE @mockup TABLE(ID INT IDENTITY,YourXML XML);
INSERT INTO @mockup VALUES
('<ContentBlock xmlns="http://corp.com/wdpr/ContentBlock">
<key xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-133036" xlink:title="entityCard" xlink:type="simple" />
<template xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132970" xlink:title="card-header-read-more-all-media" xlink:type="simple" />
<section>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132988" xlink:title="header" xlink:type="simple" />
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Make a Friend</p>
</content>
</section>
<section>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-133110" xlink:title="readMore" xlink:type="simple" />
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals at the only petting zoo in Disney’s Animal
Kingdom park.
</p>
</content>
</section>
<section>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132939" xlink:title="readAll" xlink:type="simple" />
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals.
</p>
<p xmlns="http://www.w3.org/1999/xhtml">Pet, brush and feed domesticated creatures
</p>
<ul xmlns="http://www.w3.org/1999/xhtml">
<li xmlns="http://www.w3.org/1999/xhtml">Goats</li>
</ul>
<p xmlns="http://www.w3.org/1999/xhtml">Handy animal brushes are available .
</p>
<p xmlns="http://www.w3.org/1999/xhtml">
<strong xmlns="http://www.w3.org/1999/xhtml">Keeping Clean</strong>
<br xmlns="http://www.w3.org/1999/xhtml" />Guests are encouraged to cleanse.</p>
</content>
</section>
<media>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-201994" xlink:title="media" xlink:type="simple" />
<key xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132952" xlink:title="170 x 96" xlink:type="simple" />
<image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-231377" xlink:title="section-01.jpg" xlink:type="simple" />
</media>
</ContentBlock>');
-首先我声明一个变量使搜索字符串动态化:
DECLARE @SearchFor VARCHAR(100)='Make a Friend';
--您的 XML 在最外层元素中有一个默认名称空间。
-- 是什么让事情变得有点奇怪:元素 <p>
上还有另一个默认命名空间
--我们可以用口语前缀声明这个
WITH XMLNAMESPACES(DEFAULT 'http://corp.com/wdpr/ContentBlock'
,'http://www.w3.org/1999/xlink' AS xlink
,'http://www.w3.org/1999/xhtml' AS InnerDflt )
SELECT YourXML.value('(/ContentBlock/section[(content/InnerDflt:p/text())[1]=sql:variable("@SearchFor")]/name/@xlink:href)[1]','nvarchar(max)')
FROM @mockup
查询运行如下:
从 <ContentBlock>
开始。查找 <section>
,其中 <content>
下面 <p>
的 text()
是搜索字符串。重要提示:现阶段我们还处于 <section>
的水平。所以我们可以用 <name>
继续 XPath
并在那里找到属性。
Shnugo 抢了我的风头,但我仍在 post 整理我放在一起的东西,因为它也能正常工作并演示了一些技巧(例如 *:
当你懒得添加正确的命名空间语法);)。我打算提到使用 sql:variable 将 SQL 变量传递到您的 XPath 表达式中 - shnugo 的 post 演示了如何做到这一点(它在我 posting).
-- bonus sample data
DECLARE @xml XML =
'<ContentBlock xmlns="http://corp.com/wdpr/ContentBlock">
<key xlink:href="tcm:0-133036" xlink:title="entityCard" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<template xlink:href="tcm:0-132970" xlink:title="card-header-read-more-all-media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<section>
<name xlink:href="tcm:0-132988" xlink:title="header" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Make a Friend</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-133110" xlink:title="readMore" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals at the only petting zoo in Disney’s Animal
Kingdom park.
</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-132939" xlink:title="readAll" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals.</p>
<p xmlns="http://www.w3.org/1999/xhtml">Pet, brush and feed domesticated creatures
</p>
<ul xmlns="http://www.w3.org/1999/xhtml">
<li xmlns="http://www.w3.org/1999/xhtml">Goats</li>
</ul>
<p xmlns="http://www.w3.org/1999/xhtml">Handy animal brushes are available .
</p>
<p xmlns="http://www.w3.org/1999/xhtml">
<strong xmlns="http://www.w3.org/1999/xhtml">Keeping Clean</strong>
<br xmlns="http://www.w3.org/1999/xhtml"/>Guests are encouraged to cleanse.</p>
</content>
</section>
<media>
<name xlink:href="tcm:0-201994" xlink:title="media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<key xlink:href="tcm:0-132952" xlink:title="170 x 96" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<image xlink:href="tcm:0-231377" xlink:title="section-01.jpg" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
</media>
</ContentBlock>';
DECLARE @test TABLE (someId INT IDENTITY, AppConfig XML);
INSERT @test (AppConfig) VALUES (@xml),(CAST(REPLACE(REPLACE(CAST(@xml AS VARCHAR(8000)),
'Make a Friend','xxx'),'Keeping Clean','Make a Friend') AS XML));
-- SOLUTION
WITH XMLNAMESPACES ('http://www.w3.org/1999/xlink' AS xlink)
SELECT t.someId, href = cb.x.value('(../*:name/@xlink:href)[1]', 'varchar(8000)')
FROM @test AS t
CROSS APPLY t.AppConfig.nodes('*:ContentBlock/*:section/*:content') AS cb(x)
WHERE cb.x.exist('*:p[contains(.,"Make a Friend")]') = 1;
Returns:
someId href
----------- -------------
1 tcm:0-132988
2 tcm:0-132939
我有一个 table,其中 xml 字段的内容如下:
<ContentBlock xmlns="http://corp.com/wdpr/ContentBlock">
<key xlink:href="tcm:0-133036" xlink:title="entityCard" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<template xlink:href="tcm:0-132970" xlink:title="card-header-read-more-all-media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<section>
<name xlink:href="tcm:0-132988" xlink:title="header" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Make a Friend</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-133110" xlink:title="readMore" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals at the only petting zoo in Disney’s Animal
Kingdom park.
</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-132939" xlink:title="readAll" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals.
</p>
<p xmlns="http://www.w3.org/1999/xhtml">Pet, brush and feed domesticated creatures
</p>
<ul xmlns="http://www.w3.org/1999/xhtml">
<li xmlns="http://www.w3.org/1999/xhtml">Goats</li>
</ul>
<p xmlns="http://www.w3.org/1999/xhtml">Handy animal brushes are available .
</p>
<p xmlns="http://www.w3.org/1999/xhtml">
<strong xmlns="http://www.w3.org/1999/xhtml">Keeping Clean</strong>
<br xmlns="http://www.w3.org/1999/xhtml"/>Guests are encouraged to cleanse.</p>
</content>
</section>
<media>
<name xlink:href="tcm:0-201994" xlink:title="media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<key xlink:href="tcm:0-132952" xlink:title="170 x 96" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<image xlink:href="tcm:0-231377" xlink:title="section-01.jpg" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
</media>
</ContentBlock>
我的目标是有一个查询,我可以在其中找到(例如)包含文本 "Make a Friend" 的 <p>
,然后获取 [=15= 的 xlink:href ] 元素在同一个 <section>
标签中。
我尝试了以下帖子中的几个选项:here and
这行不通
SELECT a.value1,
x.XmlCol.value('(section/content/p)[1]','VARCHAR(100)') AS SendMethod
FROM @test a
CROSS APPLY a.AppConfig.nodes('/ContentBlock') x(XmlCol)
WHERE x.XmlCol.exist('section/content/p[contains(.,"Make a Friend")]') = 1
如何获取?
提前致谢。吉列尔莫.
这样试试:
DECLARE @mockup TABLE(ID INT IDENTITY,YourXML XML);
INSERT INTO @mockup VALUES
('<ContentBlock xmlns="http://corp.com/wdpr/ContentBlock">
<key xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-133036" xlink:title="entityCard" xlink:type="simple" />
<template xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132970" xlink:title="card-header-read-more-all-media" xlink:type="simple" />
<section>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132988" xlink:title="header" xlink:type="simple" />
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Make a Friend</p>
</content>
</section>
<section>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-133110" xlink:title="readMore" xlink:type="simple" />
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals at the only petting zoo in Disney’s Animal
Kingdom park.
</p>
</content>
</section>
<section>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132939" xlink:title="readAll" xlink:type="simple" />
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals.
</p>
<p xmlns="http://www.w3.org/1999/xhtml">Pet, brush and feed domesticated creatures
</p>
<ul xmlns="http://www.w3.org/1999/xhtml">
<li xmlns="http://www.w3.org/1999/xhtml">Goats</li>
</ul>
<p xmlns="http://www.w3.org/1999/xhtml">Handy animal brushes are available .
</p>
<p xmlns="http://www.w3.org/1999/xhtml">
<strong xmlns="http://www.w3.org/1999/xhtml">Keeping Clean</strong>
<br xmlns="http://www.w3.org/1999/xhtml" />Guests are encouraged to cleanse.</p>
</content>
</section>
<media>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-201994" xlink:title="media" xlink:type="simple" />
<key xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132952" xlink:title="170 x 96" xlink:type="simple" />
<image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-231377" xlink:title="section-01.jpg" xlink:type="simple" />
</media>
</ContentBlock>');
-首先我声明一个变量使搜索字符串动态化:
DECLARE @SearchFor VARCHAR(100)='Make a Friend';
--您的 XML 在最外层元素中有一个默认名称空间。
-- 是什么让事情变得有点奇怪:元素 <p>
上还有另一个默认命名空间
--我们可以用口语前缀声明这个
WITH XMLNAMESPACES(DEFAULT 'http://corp.com/wdpr/ContentBlock'
,'http://www.w3.org/1999/xlink' AS xlink
,'http://www.w3.org/1999/xhtml' AS InnerDflt )
SELECT YourXML.value('(/ContentBlock/section[(content/InnerDflt:p/text())[1]=sql:variable("@SearchFor")]/name/@xlink:href)[1]','nvarchar(max)')
FROM @mockup
查询运行如下:
从 <ContentBlock>
开始。查找 <section>
,其中 <content>
下面 <p>
的 text()
是搜索字符串。重要提示:现阶段我们还处于 <section>
的水平。所以我们可以用 <name>
继续 XPath
并在那里找到属性。
Shnugo 抢了我的风头,但我仍在 post 整理我放在一起的东西,因为它也能正常工作并演示了一些技巧(例如 *:
当你懒得添加正确的命名空间语法);)。我打算提到使用 sql:variable 将 SQL 变量传递到您的 XPath 表达式中 - shnugo 的 post 演示了如何做到这一点(它在我 posting).
-- bonus sample data
DECLARE @xml XML =
'<ContentBlock xmlns="http://corp.com/wdpr/ContentBlock">
<key xlink:href="tcm:0-133036" xlink:title="entityCard" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<template xlink:href="tcm:0-132970" xlink:title="card-header-read-more-all-media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<section>
<name xlink:href="tcm:0-132988" xlink:title="header" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Make a Friend</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-133110" xlink:title="readMore" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals at the only petting zoo in Disney’s Animal
Kingdom park.
</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-132939" xlink:title="readAll" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals.</p>
<p xmlns="http://www.w3.org/1999/xhtml">Pet, brush and feed domesticated creatures
</p>
<ul xmlns="http://www.w3.org/1999/xhtml">
<li xmlns="http://www.w3.org/1999/xhtml">Goats</li>
</ul>
<p xmlns="http://www.w3.org/1999/xhtml">Handy animal brushes are available .
</p>
<p xmlns="http://www.w3.org/1999/xhtml">
<strong xmlns="http://www.w3.org/1999/xhtml">Keeping Clean</strong>
<br xmlns="http://www.w3.org/1999/xhtml"/>Guests are encouraged to cleanse.</p>
</content>
</section>
<media>
<name xlink:href="tcm:0-201994" xlink:title="media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<key xlink:href="tcm:0-132952" xlink:title="170 x 96" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<image xlink:href="tcm:0-231377" xlink:title="section-01.jpg" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
</media>
</ContentBlock>';
DECLARE @test TABLE (someId INT IDENTITY, AppConfig XML);
INSERT @test (AppConfig) VALUES (@xml),(CAST(REPLACE(REPLACE(CAST(@xml AS VARCHAR(8000)),
'Make a Friend','xxx'),'Keeping Clean','Make a Friend') AS XML));
-- SOLUTION
WITH XMLNAMESPACES ('http://www.w3.org/1999/xlink' AS xlink)
SELECT t.someId, href = cb.x.value('(../*:name/@xlink:href)[1]', 'varchar(8000)')
FROM @test AS t
CROSS APPLY t.AppConfig.nodes('*:ContentBlock/*:section/*:content') AS cb(x)
WHERE cb.x.exist('*:p[contains(.,"Make a Friend")]') = 1;
Returns:
someId href
----------- -------------
1 tcm:0-132988
2 tcm:0-132939