【问题标题】:T-SQL Find node with matching text and extract value from sibling node in XML fieldT-SQL 查找具有匹配文本的节点并从 XML 字段中的兄弟节点中提取值
【发布时间】:2018-12-20 14:36:31
【问题描述】:

我有一个包含如下内容的 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>

我的目标是进行查询,我可以在其中找到(例如)包含文本“结交朋友”的 &lt;p&gt;,然后在同一 &lt;section&gt; 中获取 &lt;name&gt; 元素的 xlink:href标记。

我尝试了以下帖子中的一些选项:herehere,但我没有得到我需要的结果。

这行不通

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

我怎样才能得到它?

提前致谢。吉列尔莫。

【问题讨论】:

    标签: sql-server xml tsql xpath xml-namespaces


    【解决方案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 在最外层元素中有一个默认命名空间。
    --让事情有点奇怪:元素&lt;p&gt;上还有另一个默认命名空间
    --我们可以用说话的前缀来声明它

    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
    

    查询运行如下:

    &lt;ContentBlock&gt; 开头。查找&lt;section&gt;,其中&lt;p&gt; 下方&lt;content&gt;text() 是搜索字符串。重要提示:现阶段我们仍处于&lt;section&gt; 的级别。所以我们可以继续XPath&lt;name&gt; 并在那里找到属性。

    【讨论】:

    • 哦,这超出了我的预期,有解释,清晰,整洁。非常感谢!
    【解决方案2】:

    Shnugo 抢了我的风头,但我仍在发布我整理的内容,因为它也可以工作并演示一些技巧(例如,*:,当你懒得添加正确的命名空间语法时);)。我将提到使用 sql:variable 将 SQL 变量传递到 XPath 表达式中 - shnugo 的帖子演示了如何做到这一点(我发布的内容中缺少它)。

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

    返回:

    someId      href
    ----------- -------------
    1           tcm:0-132988
    2           tcm:0-132939
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多