čtvrtek 21. ledna 2016

Poznámky z code review - vytvoření xml řetězce

Při práci s daty uloženými na SQL serveru je často nutné předat složitější data, než dovolují jednoduché datové typy vstupích parameterů. Tento problém řeší MS SQL server možností předat v parametru xml, se kterým lze následně v uložené proceduře pracovat. K vytvoření xml přistupují programátoři různě  - ale obecně je asi dobré používat jeden přístup, který by měl vycházet i z možností jazyka a "vypadat" dobře.

Samozřejmě nejjednodušší je si výsledné xml poskládat pomocí řetězců a StringBuilder třídy. Ale v následující ukázce programátor vytvořil Xml takto:
XmlDocument doc = new XmlDocument();
XmlElement FactoryList = doc.CreateElement("ContractList");
 
foreach (int cid in contractIDs)
{
   XmlElement Factory = doc.CreateElement("Contract");
   XmlAttribute ID = doc.CreateAttribute("ID");
   ID.Value = cid.ToString();
   Factory.Attributes.Append(ID);
   FactoryList.AppendChild(Factory);
}
 
doc.AppendChild(FactoryList);
 
return doc.OuterXml;

Trochu kostrbaté, když je tu Linq, který to zvládne takto:

return new XDocument(
      new XElement(
         "ContractList",
         from c in contractIDs
         select new XElement(
            "Contract",
            new XAttribute("ID"c)
         )
      )
).ToString();

V kódu jsou navíc nějaké další nedostatky - místní proměnné mají  například názvy začínající velkými písmeny, původní kód byl odněkud zkopírován - alespoň soudě dle názvů proměnných.
Ostatně kdo nikdy neprogramoval stylem Ctrl+C/Ctrl+V :-). 

3 komentáře:

  1. Neměl byste spíše ten kousek na SQL serveru. Několikrát jsem to řešil a parsing XML v SQL byl docela dost velká brzda.
    Navíc, pokud máte více různých namespace v XML, tak to musíte řešit pomocí Dynamic SQL...

    OdpovědětVymazat
    Odpovědi
    1. Přesně nerozumím, v čem je problém, jeden či více namespace není v SQL problém:

      DECLARE @xml xml

      SET @xml = '


      '


      ;WITH XMLNAMESPACES ('http://www.oppositeSide.com' as os, 'http://legal.com' as legal)
      SELECT
      ContractID = t.c.value('@ID','bigint')
      , OurAction = t.c.value('@Action', 'varchar(20)')
      , TheirAction = t.c.value('@os:Action', 'varchar(20)')
      , Legal = t.c.value('@legal:Legal', 'varchar(20)')
      FROM @xml.nodes('(/ContractList/Contract)') T(c)

      Vymazat
    2. <ContractList xmlns:os="http://www.oppositeSide.com" xmlns:st="http://legal.com">
      <Contract ID="1" Action="Accept" os:Action="Cancel" st:Legal="No"/>
      <Contract ID="2" Action="Accept" os:Action="Accept" st:Legal="Maybe"/>
      </ContractList>

      Vymazat