Extracting singleton value from xml list - sql

I am familiar with extracting values from xml using SQL in SQL Server, but now I need to identify the parent node with a particular "key node" value and get the value from its "value node."
<example>
<item>
<key>skip</key>
<value>True</value>
</item>
<item>
<key>test</key>
<value>True</value>
</item>
<item>
<key>number</key>
<value />
</item>
<item>
<key>country</key>
<value>USA</value>
</item>
<item>
<key>Account Number</key>
<value>1111111111</value>
</item>
<item>
<key>website</key>
<value>stackoverflow</value>
</item>
<item>
<key>type</key>
<value>Customer</value>
</item>
</example>
If I want to get the account number I could use this sql statement:
SELECT xml.value('(example/item/value)[5]','varchar(30)')
Since the item node is 5th down on the list, the singleton will be 5. But what if the position of the account number node can change? I want to be able to identify the account number based on the condition that key = 'Account Number.'
In other words, I want to SELECT value where key = 'Account Number'

The trick is to specify WHICH "item" you want in brackets, by specifying a key/value that is unique to the item. In this case, you want the one where the "key" node has the text "Account Number". You'd express it like this:
SELECT #xml.value('(example/item[key="Account Number"]/value)[1]','varchar(30)')

Related

Build New XML From Stored XML Value

We store rather large XML blobs (in an column of XML type) and I'm pursuing a skunkworks project to try to build up a subset of the XML on the fly when needed.
Let's say I have this XML blob stored in our database table in a given column:
<root>
<header>
<id>1</id>
<name id="foo">Name</name>
</header>
<body>
<items>
<addItem>
<val>1</val>
</addItem>
<observeItem>
<val>2</val>
</observeItem>
</items>
</body>
</root>
What I want to get out is this is to basically recreate the above document structure but only include one of the items children, so for example:
<root>
<header>
<id>1</id>
<name id="foo">Name</name>
</header>
<body>
<items>
<observeItem>
<val>2</val>
</observeItem>
</items>
</body>
</root>
If I were interested in just the observeItem record (the items element can have any number of children, but I'll only ever be interested in a single one of them).
I know I can do something like SELECT #XML.query('//items/child::*[2]') to get just a given child item, but how would I build up the full original document in a query with just one of those children?
I've come up with a solution, but I'm not entirely pleased with it:
DECLARE #XML XML = '
<root>
<header>
<id>1</id>
<name id="foo">Name</name>
</header>
<body>
<items>
<addItem>
<val>1</val>
</addItem>
<observeItem>
<val>2</val>
</observeItem>
</items>
</body>
</root>'
DECLARE #NthChild INT = 2
SELECT
#XML.query('//header'),
#XML.query('//items/child::*[sql:variable("#NthChild")]') AS 'items'
FOR XML PATH('root')
I don't like having to specify the root explicitly nor the items, but I think this approach could get me by.

Speech Recognition Grammar Specification: semantic results

I'm currently developing an application of Speech Recognition using Microsoft Kinect SDK. The goal of the application is to load any (valid) XML file containing the grammar and use it to process speech.
I'm in the process of testing the application by developing not so simple grammars and during that process I haven't figured out how to return specific semantic values, in particular names. For example, in the following grammar:
<grammar version="1.0" xml:lang="en-US" root="rootRule" tag-format="semantics/1.0-literals" xmlns="http://www.w3.org/2001/06/grammar">
<!-- Ask for person's related information (age, location, name, etc.) -->
<rule id="rootRule">
<one-of>
<!-- Ask person name -->
<item>
<tag>AnswerToNameQuestion</tag>
<one-of>
<item> my name is </item>
<item> people call me </item>
</one-of>
<ruleref uri="#names"/>
</item>
<!-- Ask person location -->
<item>
<tag>QuestionOfLocation</tag>
<one-of>
<item> do you know where is </item>
<item> can you tell me where </item>
<item> where did </item>
</one-of>
<ruleref uri="#names"/>
</item>
</one-of>
</rule>
<!-- Answer person name -->
<rule id="names">
<item>
<one-of>
<item> peter </item>
<item> john </item>
<item> danny </item>
</one-of>
</item>
</rule>
</grammar>
When a person says their name, I want the semantic to be the name of that person. For example, for the question "What is your name" (not included in this grammar), and a reply "My name is -insert name-", I wanted the semantic results to be the name of the person and not simply "AnswerToNameQuestion" semantic result that is being returned right now.
Any help would be greatly appreciated!
In the SpeechRecognized event handler. You can get the "textual sentence" if you query the event.Result.Text property instead of event.Result.Semantics.Value. You can use this second property to remove from text string the non-relevant portion.
For example, if somebody says "my name is Peter", inside SpeechRecognized event handler you will have:
event.Result.Text = "my name is Peter"
event.Result.Semantics.Value = "AnswerToNameQuestion"

Unable to understand some XSLT grouping code through <xsl:key and generate-id()

I have data in the below XML format
<item>
<title>Body Cleaner</title>
<vendor>Wipro</vendor>
<location>EMEA</location>
<manufacture_date>12/08/2010</manufacture_date>
<item_type>House Hold</item_type>
<item_type>Health</item_type>
</item>
<item>
<title>Sweet Catch up</title>
<vendor>Unilever</vendor>
<location>APAC</location>
<manufacture_date>21/07/2013</manufacture_date>
<item_type>House Hold</item_type>
<item_type>Kitchen</item_type>
</item>
(1) Below is code in a xsl file
<xsl:key name="groups" match="item_type" use="."/>
and
<xsl:apply-templates select="item/item_type[generate-id() = generate-id(key('groups', .)[1])]"/>
here i am unable to understand the use of generate-id() in that particular case . What is the purpose of below code
[generate-id() = generate-id(key('groups', .)[1])]
(1) Below is code in another xsl file
<xsl:key name="vendors" match="item" use="vendor"/>
and
<xsl:apply-templates select="item[count(.|key('vendors',vendor)[1])=1]">
here i am unable to understand the expression
item[count(.|key('vendors',vendor)[1])=1]
specially the purpose of .| in count.
Could somebody help me to make the ground here so that i can further understand the XSLT code.
Thanks
This is called muenchian grouping. In xslt 1.0, there was no built in grouping.
Keys, like this one are used by the key() function:
<xsl:key name="vendors" match="item" use="vendor"/>
The key() function returns a node-set from the document, using the index specified by an element (info).
item[count(.|key('vendors',vendor)[1])=1]
This will see whether a node set is made up of the two nodes has one or two nodes in it (e.g.grouping). This basically identifies the groups. Once you have Identified the groups you can visit each node in the key.

sql + xquery to delete multiple parent nodes

In the below xml i have three 5 /Item elements, 4 of which have a Blob child element. I want to delete the elements that have a child Blob element but only where Item/#Name has the text "Blob" in it.
<Items>
<Item Name="Blob123">
<Blob/>
</Item>
<Item Name="Blob124">
<Blob/>
</Item>
<Item Name="Blob125">
<Blob/>
</Item>
<Item Name="Blob126">
</Item>
<Item Name="Xyz126">
<Blob/>
</Item>
</Items>
This query returns the 3 /Item elements named 'Blob%' and with a child /Blob element just fine.
select xmlVal.query('(/Items/Item[contains(#Name, "Blob")]/Blob/..)')
However when i attempt to delete those element using this xquery:
select xmlVal.modify('delete (/Items/Item[contains(#Name, "Blob")]/Blob/..)')
I get: Incorrect use of the XML data type method 'modify'. A non-mutator method is expected in this context.
What am i doing wrong.
In case it helps others, to fix this i need to use update/set and also needed to change the xpath slightly
update table1
set xmlVal.modify('delete (/Items/Item[contains(#Name, "Blob")][Blob])')

how to avoid sequence using XSD

i want a particular sequence to be generated in a random manner
<item>
<i1>abc</i1>
<i2>pqr</i2>
</item>
now how can i make an xsd where <i1> can come before <i2> ?
use the 'all' indicator as shown on the w3schools website