TSQL Shred XML - Arbeiten mit Namespaces
-
24-10-2019 - |
Frage
OK, ich bin ein C# ASP.NET -Entwickler, das nach Bestellungen beauftragt ist: Die Bestellungen sollen einen bestimmten Datensatz entgegennehmen, die XML -Spalten zerkleinern und Spalten zurückgeben. Ich habe argumentiert, dass es einfacher ist, das Shredding auf der ASP.NET -Seite zu erledigen, wo wir bereits Zugriff auf Dinge wie Deserializer usw. und den gesamten Komplex bekannter Typen haben, aber nein, der Chef sagt: " Gibt einen Datensatz zurück, binden Sie den Datensatz an die Spalten der Gridview ", also mache ich vorerst das, was mir gesagt wurde. Dies ist alles, um sich von den Leuten zu bewegt, die mitkommen und "schlechte Anforderungen" sagen.
Aufgabe zur Hand:
Aktueller Code, der nicht funktioniert:
Und wenn wir den vorherigen Beitrag so ändern, dass Namespaces in die XML -Elemente aufgenommen wird, verlieren wir die Funktionalität, die der vorherige Beitrag hat ...
DECLARE @table1 AS TABLE (
ProductID VARCHAR(10)
, Name VARCHAR(20)
, Color VARCHAR(20)
, UserEntered VARCHAR(20)
, XmlField XML
)
INSERT INTO @table1 SELECT '12345','ball','red','john','<sizes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><size xmlns="http://example.com/ns" name="medium"><price>10</price></size><size xmlns="http://example.com/ns" name="large"><price>20</price></size></sizes>'
INSERT INTO @table1 SELECT '12346','ball','blue','adam','<sizes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><size xmlns="http://example.com/ns" name="medium"><price>12</price></size><size xmlns="http://example.com/ns" name="large"><price>25</price></size></sizes>'
INSERT INTO @table1 SELECT '12347','ring','red','john','<sizes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><size xmlns="http://example.com/ns" name="medium"><price>5</price></size><size xmlns="http://example.com/ns" name="large"><price>8</price></size></sizes>'
INSERT INTO @table1 SELECT '12348','ring','blue','adam','<sizes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><size xmlns="http://example.com/ns" name="medium"><price>8</price></size><size xmlns="http://example.com/ns" name="large"><price>10</price></size></sizes>'
INSERT INTO @table1 SELECT '23456','auto','black','ann','<auto xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><type xmlns="http://example.com/ns">car</type><wheels xmlns="http://example.com/ns">4</wheels><doors xmlns="http://example.com/ns">4</doors><cylinders xmlns="http://example.com/ns">3</cylinders></auto>'
INSERT INTO @table1 SELECT '23457','auto','black','ann','<auto xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><type xmlns="http://example.com/ns">truck</type><wheels xmlns="http://example.com/ns">4</wheels><doors xmlns="http://example.com/ns">2</doors><cylinders xmlns="http://example.com/ns">8</cylinders></auto><auto xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><type xmlns="http://example.com/ns">car</type><wheels xmlns="http://example.com/ns">4</wheels><doors xmlns="http://example.com/ns">4</doors><cylinders xmlns="http://example.com/ns">6</cylinders></auto>'
DECLARE @x XML
-- I think I'm supposed to use WITH XMLNAMESPACES(...) here but I don't know how
SELECT @x = (
SELECT
ProductID
, Name
, Color
, UserEntered
, XmlField.query('
for $vehicle in //auto
return <auto
type = "{$vehicle/type}"
wheels = "{$vehicle/wheels}"
doors = "{$vehicle/doors}"
cylinders = "{$vehicle/cylinders}"
/>')
FROM @table1 table1
WHERE Name = 'auto'
FOR XML AUTO
)
SELECT @x
SELECT
ProductID = T.Item.value('../@ProductID', 'varchar(10)')
, Name = T.Item.value('../@Name', 'varchar(20)')
, Color = T.Item.value('../@Color', 'varchar(20)')
, UserEntered = T.Item.value('../@UserEntered', 'varchar(20)')
, VType = T.Item.value('@type' , 'varchar(10)')
, Wheels = T.Item.value('@wheels', 'varchar(2)')
, Doors = T.Item.value('@doors', 'varchar(2)')
, Cylinders = T.Item.value('@cylinders', 'varchar(2)')
FROM @x.nodes('//table1/auto') AS T(Item)
Wenn mein vorheriger Beitrag zeigt, dass es eine viel bessere Möglichkeit gibt, dies zu tun, muss ich diese Frage auch wirklich überarbeiten, aber da dieses Codierungsstil gut ist, kann ich diese IS wahrscheinlich mit dieser IS fortsetzen.
Lösung
DECLARE @x XML;
with xmlnamespaces ('http://www.w3.org/2001/XMLSchema-instance' as xsi
, 'http://www.w3.org/2001/XMLSchema' as xsd
, 'http://example.com/ns' as ns)
SELECT @x = (
SELECT
ProductID
, Name
, Color
, UserEntered
, XmlField.query('
for $vehicle in //auto
return <auto
type = "{$vehicle/ns:type}"
wheels = "{$vehicle/ns:wheels}"
doors = "{$vehicle/ns:doors}"
cylinders = "{$vehicle/ns:cylinders}"
/>')
FROM @table1 table1
WHERE Name = 'auto'
FOR XML AUTO
)