2

I've a table with an xml field having content like this:

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

My goal is to have a query where I can find (for example) the <p> that contains the text "Make a Friend", then get the xlink:href of the <name> element in the same <section> tag.

I tried a few options like in this posts: here and here but I'm not getting the results I need.

This doesn't work

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

How can I get it?

Thanks in advance. Guillermo.

2 Answers 2

3

Try it like this:

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

-First I declare a variable to make the search-string dynamic:

DECLARE @SearchFor VARCHAR(100)='Make a Friend';

--Your XML has a default namespace in the outermost element.
--What makes things a bit weird: There is another default namespace on the element <p>
--We can declare this with a speaking prefix

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

The query runs as this:

Start with <ContentBlock>. Look for a <section>, where the text() of <p> below <content> is the search-string. Important: At this stage we are still on the level of <section>. So we can continue the XPath with <name> and find the attribute there.

Sign up to request clarification or add additional context in comments.

1 Comment

Oh, that's more than I expected, with explanation, clear, neat. Thank you so much!
1

Shnugo stole my thunder but I'm still posting what I put together as it will work as well and demonstrates a few tricks (e.g. *: for when you're too lazy to add the correct namespace syntax) ;). I was going to mention the use of sql:variable to pass a SQL variable into your XPath expressions - shnugo's post demonstrates how to do that (it's missing in what I'm 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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.