2009-09-04 8 views
1

REMARQUE: j'ai résolu la majorité de ce problème mais j'ai rencontré un problème. Lisez en bas s'il vous plaît. Vous verrez où j'ai ajouté une section (NOTE). TIA. POUR CHEMIN XML dans SQL Server


J'ai une requête de jointure plutôt étendue que je veux faire basculer en XML. Je l'ai presque fonctionné mais il me manque un concept quelque part ici. Ma requête (en abrégé) ressemble à:

SELECT Campaign.CampaignId "Campaign/ID" 
     , Campaign.CompanyId "Campaign/CompanyID" 
     , Campaign.CampaignName "Campaign/Name" 
... 
     , Audio.AudioID "Campaign/Audio/ID" 
     , Audio.[Name] "Campaign/Audio/Name" 
... 
     , Video.CampaignVideosAudioMute "Campaign/Video/Audio/Mute" 
     , Video.CampaignVideosAudioVolume "Campaign/Video/Audio/Volume" 
     , Video.CampaignVideosPositionX "Campaign/Video/Position/X" 
... 
     , Characters.CharacterID "Campaign/Characters/Character/ID" 
     , Characters.[Name] "Campaign/Characters/Character/Name" 
... 
     , Element.ElementID "Campaign/Elements/Element/ID" 
     , Element.Editable "Campaign/Elements/Element/Editable" 
... 
     , [Image].ImageID "Campaign/Elements/Element/Image/ID" 
     , [Image].[Path] "Campaign/Elements/Element/Image/Path" 
... 
     , [Text].TextID "Campaign/Elements/Element/Text/ID" 
     , [Text].Value "Campaign/Elements/Element/Text/Value" 
FROM vwCampaign Campaign 
LEFT JOIN dbo.vwCampaignAudio Audio ON Campaign.CampaignId = Audio.CampaignId 
LEFT JOIN dbo.vwCampaignCharacters Characters ON Campaign.CampaignId = Characters.CampaignId 
LEFT JOIN dbo.vwCampaignVideo Video ON Campaign.CampaignId = Video.CampaignId 
LEFT JOIN dbo.vwCampaignElements Element ON Campaign.CampaignId = Element.CampaignId 
LEFT JOIN dbo.vwCampaignElementImage [Image] ON Element.CampaignId = [Image].CampaignId AND Element.ElementID = [Image].ElementID 
LEFT JOIN dbo.vwCampaignElementText [Text] ON Element.CampaignId = [Text].CampaignId AND Element.ElementID = [Text].ElementID 
WHERE Campaign.CampaignId = 10370 
FOR  XML PATH, ELEMENTS XSINIL 

La façon dont les données fonctionne je:

  • 1 campagne ligne
  • 1 rang audio - liés à la campagne ligne
  • 1 vidéo ligne - en rapport avec la campagne ligne
  • 1 rangées de caractères - liées à la ligne de la campagne
  • 1-n rangées d'éléments - en relation avec la ligne de la campagne
  • 0 ou 1 lignes d'image - associées à chaque rangée d'éléments
  • 0 ou 1 lignes de texte - associées à chaque rangée d'éléments

Le XML sort comme:

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <Campaign> 
    <ID>10370</ID> 
    <CompanyID>C2811EA3-361A-411A-BB4C-816A5D6C12DB</CompanyID> 
    <Name>Keith01</Name> 
    <URL>http://kab.rivworks.com/tests/kab02.htm</URL> 
    <Module>Coupon</Module> 
    <StartDate>2009-06-29T12:05:00</StartDate> 
    <EndDate>2021-06-30T18:00:00</EndDate> 
    <Notes>Test #1</Notes> 
    <Meta>D7E7D735-8D64-4127-84B1-7D72FB5EDD17</Meta> 
    <Orientation>Half-Body Left</Orientation> 
    <PresentationPlayerFlashVars>config=http://cdn1.deal4it.com/rivworks/demos/skymall/skymall-coupon-3.xml</PresentationPlayerFlashVars> 
    <Player> 
     <CookieIdentity>honirjymcvzk</CookieIdentity> 
     <Stage> 
     <Top></Top> 
     <Left></Left> 
     <Height>423</Height> 
     <Width>500</Width> 
     <MarginLeft></MarginLeft> 
     <Container> 
      <Background> 
      <Color>0xffffff</Color> 
      <Image></Image> 
      </Background> 
     </Container> 
     </Stage> 
    </Player> 
    <Audio> 
     <ID xsi:nil="true" /> 
     <Name xsi:nil="true" /> 
     <Path xsi:nil="true" /> 
     <Meta xsi:nil="true" /> 
     <Genre xsi:nil="true" /> 
    </Audio> 
    <Video> 
     <ControlbarEvent>visible</ControlbarEvent> 
     <Event>play</Event> 
     <PresentationSkin>https://widgets.rivworks.com/player/latest/rivplayer.swf</PresentationSkin> 
     <Audio> 
     <Mute>False</Mute> 
     <Volume>100</Volume> 
     </Audio> 
     <Position> 
     <X>19</X> 
     <Y>140</Y> 
     </Position> 
     <About> 
     <Text>RIV Works</Text> 
     <Url>http://www.deal4it.com</Url> 
     </About> 
     <Size> 
     <Height>266</Height> 
     <Width>400</Width> 
     </Size> 
     <Settings> 
     <Autostart>True</Autostart> 
     <Buffer>1</Buffer> 
     <DelayPlay>0</DelayPlay> 
     <Item>0</Item> 
     <Quality>True</Quality> 
     <Repeat>none</Repeat> 
     </Settings> 
    </Video> 
    <Character> 
     <ID>19029FFC-C1C0-4134-B813-93A9FF17C7F6</ID> 
     <Name>Jenna</Name> 
     <Actor>CD5AF2B6-C39A-4316-BFB0-D4450194EC80</Actor> 
     <Meta>10041662-305F-4493-ACB3-460D687306A4</Meta> 
     <Access>Public</Access> 
     <Configuration>Individual</Configuration> 
     <ImageThumbnail>http://cdn1.deal4it.com/rivworks/images/headshots/jenna.jpg</ImageThumbnail> 
     <isPublic>1</isPublic> 
     <Demographics> 
     <Age>31 - 40</Age> 
     <Ethnicity>Caucasian</Ethnicity> 
     <Gender>Female</Gender> 
     </Demographics> 
    </Character> 
    <Elements> 
     <Element> 
     <ID>D9B2A643-73EC-4D55-BA34-D643113CEDEA</ID> 
     <Editable>1</Editable> 
     <Meta>D5F6175C-8DC7-4F18-9A5F-E2021579498B</Meta> 
     <Position> 
      <Level>2</Level> 
      <X>464</X> 
      <Y>21</Y> 
     </Position> 
     <Image> 
      <ID>90FF7F5A-75EC-4FB5-81B1-B9BEC4E8A22A</ID> 
      <Path>http://developer.rivworks.com/images/a5b19fe8-c8d3-4588-9eac-7cdf39b52078.jpg</Path> 
      <Link></Link> 
      <Target></Target> 
      <Meta>97261982-2131-41F7-9E2C-ADB10E31ED20</Meta> 
      <Size> 
      <Height>16</Height> 
      <Width>16</Width> 
      </Size> 
     </Image> 
     <Text> 
      <ID xsi:nil="true" /> 
      <Value xsi:nil="true" /> 
      <Link xsi:nil="true" /> 
      <Target xsi:nil="true" /> 
      <Meta xsi:nil="true" /> 
      <FontColor xsi:nil="true" /> 
      <FontFamily xsi:nil="true" /> 
      <FontSize xsi:nil="true" /> 
     </Text> 
     </Element> 
    </Elements> 
    </Campaign> 
</row> 

Malheureusement, j'ai quelques problèmes avec cela.

  1. L'élément racine est toujours au niveau de la ligne. L'élément racine doit être
  2. Si j'ai 3 caractères et 3 éléments je me retrouve avec éléments racine. La seule chose qui change d'un élément racine à l'autre est quel caractère et quel élément est visible. (Et ce composé avec chaque élément ayant 0 ou 1 textes et/ou images)

Le XML devrait venir à la recherche quelque chose comme:

<campaign> 
    <ID>10370</ID> 
    <CompanyID>C2811EA3-361A-411A-BB4C-816A5D6C12DB</CompanyID> 
    <etc>...</etc> 
    <Characters> 
    <Character> 
     <data>...</data> 
    <Character> 
    <Character> 
     <data>...</data> 
    <Character> 
    </Characters> 
    <Elements> 
    <Element> 
     <data>...</data> 
     <Image>...</Image> 
     <Text>...</Text> 
    <Element> 
    <Element> 
     <data>...</data> 
     <Image>...</Image> 
     <Text>...</Text> 
    <Element> 
    </Elements> 
</campaign> 

Que dois-je changer? Ai-je besoin de regarder une méthode différente de créer mon XML, peut-être une sorte de clause d'imbrication?


REMARQUE: Après avoir joué et beaucoup de googler/fringales J'ai changé ma requête afin qu'il utilise les requêtes imbriquées. Voici à quoi il ressemble maintenant:

SELECT Campaign.CampaignId  "Campaign/ID" 
      , Campaign.CompanyId  "Campaign/CompanyID" 
      , Campaign.CampaignName "Campaign/Name" 
... 
      , Audio.AudioID "Campaign/Audio/ID" 
      , Audio.[Name] "Campaign/Audio/Name" 
... 
      , Video.CampaignVideosControlbarEvent "Campaign/Video/ControlbarEvent" 
      , Video.CampaignVideosEvent  "Campaign/Video/Event" 
      , (SELECT cc.CharacterID "Character/ID" 
      , cc.[Name]  "Character/Name" 
       FROM dbo.vwCampaignCharacters cc 
       WHERE cc.CampaignID = Campaign.CampaignId 
       FOR XML PATH ('') 
      ) AS "Campaign/Characters" 
      , (SELECT ce.ElementID  "Element/ID" 
        , ce.Editable   "Element/Editable" 
        , ce.Meta    "Element/Meta" 
        , ce.PositionLevel "Element/Position/Level" 
        , ce.PositionX  "Element/Position/X" 
        , ce.PositionY  "Element/Position/Y" 
        , (SELECT cei.ImageID   "Image/ID" 
          , cei.[Path]   "Image/Path" 
          , cei.Link   "Image/Link" 
          , cei.Target   "Image/Target" 
          , cei.Meta   "Image/Meta" 
          , cei.SizeHeight  "Image/Size/Height" 
          , cei.SizeWidth  "Image/Size/Width" 
         FROM dbo.vwCampaignElementImage cei 
         WHERE cei.CampaignID = ce.CampaignId 
         AND cei.ElementID = ce.ElementID 
         FOR XML PATH ('') 
        ) AS "Element" 
        , (SELECT cet.TextID   "ID" 
          , cet.Value   "Value" 
          , cet.Link   "Link" 
          , cet.Target   "Target" 
          , cet.Meta   "Meta" 
          , cet.FontColor  "FontColor" 
          , cet.FontFamily  "FontFamily" 
          , cet.FontSize  "FontSize" 
         FROM dbo.vwCampaignElementText cet 
         WHERE cet.CampaignID = ce.CampaignId 
         AND cet.ElementID = ce.ElementID 
         FOR XML PATH ('Text') 
        ) AS "Element" 
       FROM dbo.vwCampaignElements ce 
       WHERE ce.CampaignID = Campaign.CampaignId 
       FOR XML PATH ('Element') 
      ) AS "Campaign/Elements" 

    FROM vwCampaign Campaign 
    LEFT JOIN dbo.vwCampaignAudio Audio ON Campaign.CampaignId = Audio.CampaignId 
    LEFT JOIN dbo.vwCampaignVideo Video ON Campaign.CampaignId = Video.CampaignId 
    WHERE Campaign.CampaignId = 10370 
    FOR XML PATH ('Campaign'), ROOT ('Campaigns'), ELEMENTS XSINIL 

Le XML sort presque parfait maintenant sauf pour le balisage des sous-requêtes.

<Campaigns xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <Campaign> 
    <Campaign> 
     <ID>10370</ID> 
     <CompanyID>C2811EA3-361A-411A-BB4C-816A5D6C12DB</CompanyID> 
     <Name>Keith01</Name> 
... 
     <Characters>&lt;Character&gt;&lt;ID&gt;19029FFC-C1C0-4134-B813-93A9FF17C7F6&lt;/ID&gt;&lt;Name&gt;Jenna&lt;/Name&gt; ... 
     <Elements>&lt;Element&gt;&lt;Element&gt;&lt;ID&gt;D9B2A643-73EC-4D55-BA34-D643113CEDEA&lt;/ID&gt;&lt;Editable&gt;1&lt;/Editable&gt; ... 
    </Campaign> 
    </Campaign> 
</Campaigns> 

Le sous-requêtes de caractères et l'élément produisent & lt;/& gt; au lieu de < />, comment dites-vous, URL safe markup? Je ne veux pas ça.Les sous-sous-requêtes Image et Texte produisent & amp & lt;/& amp & gt; au lieu de < />. Notez qu'il a été sécurisé deux fois en URL! Je ne le veux pas non plus.

Toute idée de la façon d'obtenir le balisage réel au lieu de cela merde. :)

TIA

Répondre

6

Vous devriez probablement transférer la 'campagne' dans le PATH:

SELECT Campaign.CampaignId "ID"  
, Campaign.CompanyId "CompanyID"  
, Audio.AudioID "Audio/ID"  
, Audio.[Name] "Audio/Name" 
...  
FROM vwCampaign Campaign 
LEFT JOIN dbo.vwCampaignAudio Audio 
... 
WHERE Campaign.CampaignId = 10370 
FOR  XML PATH('Campaign'), ELEMENTS XSINIL 

Mise à jour

Pour le problème de suqueries, vous devez utiliser le FOR XML PATH(..),TYPE pour créer une valeur XML typée (par opposition à une chaîne contenant xml). Une sous-requête typée XML créera un élément XML, une chaîne insérera simplement le résultat en tant que text() et sera échappée.

select a, (select b from t for xml path("b"), type) as "*" 
from ... for xml path("a") 
+1

Merci pour cela. Je l'ai ajouté en plus d'un attribut ROOT (au cas où je ne sélectionne pas une seule campagne). Cela résout un de mes nombreux défis sur celui-ci! –

+0

Il était temps que j'apprenne que FOR XML a une option ROOT lol. Merci pour ça. –

+0

Voir mise à jour dans mon poste pour le sous-question XML –

Questions connexes