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
Related
I have an XML data field in one of my tables that essentially looks like this:
<App xmlns='http://Namespace1'>
<Package xmlns='http://Namespace2'>
<Item>
<ItemDetails xmlns='http://Namespace3'>
<ItemName>ItemNameValue</ItemName>
</ItemDetails>
other_item_stuff
</Item>
<Item>
<ItemDetails>
<ItemName>ItemNameValue</ItemName>
</ItemDetails>
</Item>
...
</Package>
</App>
I need to get all of the ItemNameValues from the XML.
I have tried to adapt many examples found on the web to my purpose, but have failed miserably. The best I seem to be able to do is get one ItemName per Package.
I think that CROSS APPLY is where I need to go, but the syntax to retrieve all the itemdetail.itemname eludes me.
This is my latest failure (returns nothing):
WITH XMLNAMESPACES(
'http://Namespace1' AS xsd,
'http://www.w3.org/2001/XMLSchema-instance' AS xsi,
'http://Namespace2' AS ns1,
'http://Namespace3' AS ns2)
Items.d.value('(ns2:ItemDetails/ItemName/text())[1]','varchar(200)') as
ItemName
FROM MyTable
CROSS APPLY XMLDataColumn.nodes('/xsd:App/ns1:Package/ns1:Item') Items(d)
I hope to get several records from each XML field, but can only ever get the first element.
The biggest problem in this issue is the XML itself:
<App xmlns="http://Namespace1">
<Package xmlns="http://Namespace2">
<Item>
<ItemDetails xmlns="http://Namespace3">
<ItemName>ItemNameValue</ItemName>
</ItemDetails>
other_item_stuff
</Item>
<Item>
<ItemDetails>
<ItemName>ItemNameValue</ItemName>
</ItemDetails>
</Item>
...
</Package>
</App>
Two major Problems:
The namespaces are all declared as default namespaces (they do not include a prefix). All nodes within a node share the same default namespace, if there is nothing else stated explicitly.
The first <ItemDetails> is living within namespace http://Namespace3, while the second <ItemDetails> is living within namespace http://Namespace2 (inherited from <Package>)
That means: If you can - by any chance - change the construction of the XML, try to do this first.
If you have to deal with this, you can try this clean, but clumsy approach.
WITH XMLNAMESPACES(
'http://Namespace1' AS ns1,
'http://www.w3.org/2001/XMLSchema-instance' AS xsi,
'http://Namespace2' AS ns2,
'http://Namespace3' AS ns3)
SELECT COALESCE(Items.d.value('(ns2:ItemDetails/ns2:ItemName/text())[1]','varchar(200)')
,Items.d.value('(ns3:ItemDetails/ns3:ItemName/text())[1]','varchar(200)')) AS ItemName
FROM #xml.nodes('/ns1:App/ns2:Package/ns2:Item') Items(d);
Another approach is to use a namespace wildcard, but be aware of ambigous names...
SELECT Items.d.value('(*:ItemDetails/*:ItemName/text())[1]','varchar(200)') AS ItemName
FROM #xml.nodes('/*:App/*:Package/*:Item') Items(d)
I'm working with SQL data hosted by a 3rd party, and am trying to pull some specific information for reporting. However, some of what I need to parse out is in XML format, and I'm getting stuck. I'm looking for the syntax to pull the text= values only from the XML code.
I believe the code should something like this, but most of the examples I can find online involve simpler XML hierarchy's than what I'm dealing with.
<[columnnameXML].value('(/RelatedValueListBO/Items/RelatedValueListBOItem/text())[1]','varchar(max)')>
Fails to pull any results. I've tried declaring the spacenames as well, but again...I only ever end up with NULL values pulled.
Example XML I'm dealing with:
<RelatedValueListBO xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/RelatedValueListBOSchema.xsd">
<Items>
<RelatedValueListBOItem groupKey="Response1" text="Response1" selected="true" />
<RelatedValueListBOItem groupKey="Response2" text="Response2" selected="true" />
<RelatedValueListBOItem groupKey="Response3" text="Response3" selected="true" />
</Items>
</RelatedValueListBO>
Ideally I'd like to pull response1; response2; response3 into a single column. Allowing for the fact that multiple responses may exist. I believe I'm getting stuck with the basic code I've been trying due to the namespaces associated to RelatedValueListBO and the fact that what I want is grouped in groupKey, text, and selected, instead of the value I want just being under the Items node.
You have the namespaces defined in your XML, so you need to define them in the XQuery too.
Fast and dirty method is to replace all namespaces with a "*":
SELECT #x.value('(/*:RelatedValueListBO/*:Items/*:RelatedValueListBOItem/#text)[1]','varchar(max)')
To get all responses in a single column you can use:
SELECT
Item.Col.value('./#text','varchar(max)') X
FROM #x.nodes('/*:RelatedValueListBO/*:Items/*:RelatedValueListBOItem') AS Item(Col)
If you need a better performance, you may need to define namespaces properly.
You can use something like this to extract the value of "text" in the first node of RelatedValueListBOItem
SELECT extractvalue(value(rs), '//RelatedValueListBOItem[1]/#text')
FROM TABLE (xmlsequence(extract(sys.xmltype('<RelatedValueListBO>
<Items>
<RelatedValueListBOItem groupKey="Response1" text="Response1"
selected="true" />
<RelatedValueListBOItem groupKey="Response2" text="Response2"
selected="true" />
<RelatedValueListBOItem groupKey="Response3" text="Response3"
selected="true" />
</Items>
</RelatedValueListBO>'),'/RelatedValueListBO/Items'))) rs;
I am trying to create a data file for my application with XML as input and map it to my HP Exstream variables. But when I am trying to save the file it is giving me error "No customer-level tag specified! Engine will not process.". I am not sure how to resolve this error. There is no customer level information I want in my input. Can anyone explain what is this error and how to resolve it?
What HP Exstream is telling you is that you have not defined a tag that will allow Exstream to know when a customer begins and ends. This does not have to be a tag that says <customer-level>, but rather the tag you are using in the XML to determine where a customer begins and ends.
When you are using an XML file as input, you may be dealing with multiple customers take this for example:
<item>
<address>
<line>a</line>
<line>b</line>
</address>
<body>Hello World</body>
</item>
<item>
<address>
<line>c</line>
<line>d</line>
</address>
<body>Hello Universe</body>
</item>
I would be using the <item> tag to tell HP Exstream where my customer begins and ends.
You can choose the customer tag in the properties of the tags.
I have a small dilemma.
If you have the following URI endpoints:
/item
/item/{id}
If I make a GET request to /item I expect something like this:
<Items>
<Item>...</Item>
<Item>...</Item>
...
</Items>
If I make a GET request to /item/{id} I expect something like this:
<Item>
...
</Item>
Some of my fellow team members argue we should design the API so when someone does a GET for /item/{id} it should be returned as a collection of a single element. Like this:
<Items>
<Item>...</Item>
</Items>
This seems wrong to me. Does it seem wrong to you too? Please explain why, so I might convince either myself to go with the always wrapped version of the resource or my fellow devs to go with the non-wrapped single resource.
Most importantly, there is no right and wrong answer to this question.
However, here is what I think.
If you want to return a single item, I would tend to do this:
GET /Item/{Id}
=>
<Item>
...
</Item>
If the {Id} does not exist then the server should return a 404.
If I want to return a collection of items, I would do
GET /Items
=>
<Items>
<Item>...</Item>
<Item>...</Item>
</Items>
If there are no items, then it should return a 200 with an empty <Items/> element.
If it really makes it easier for the client to deal with a collection that has just one element, then you could do something like this.
GET /Items?Id={Id}
=>
<Items>
<Item> ... </Item>
</Items>
The difference here is that if the {Id} did not exist then I would tend to return 200 not a 404.
Seems counterintuitive to me. You are potentially saving code effort on the client side by having one way of reading data from your two GET methods. This is of course countered by having extra code to wrap your single GET method in a collection.
If you want real world examples,
twitter returns an individual
representation of a resource not
wrapped in a collection
basecamp, an
early proponent of REST based API,
also follows this model
EDIT: Our API uses this HTTP status code structure
I think your colleagues are right if you think about the consuming side of your REST service, which then can handle every response as a collection. And there's one more thing: If the {id} did not exist, what does your service return? Nothing? Then the consumer has to check for either a null result or error response, a single element or a collection. According to my experience getting a collection in any case (which may be empty) is the most convenient way to be served by a REST service.
WCF Rest Starter Kit OnGetItems returns IEnumerable<KeyValuePair<string,BusinessObject>>
On serialization , It becomes
<ItemInfoList>
<ItemInfo>
<EditLink>http://localhost:1394/BService.svc/1</EditLink>
<Item>
<Name>Foundations</Name>
</Item>
</ItemInfo>
<ItemInfo>
<EditLink>http://localhost:1394/Service.svc/2</EditLink>
<Item>
<Name>Hitchhikers guide</Name>
</Item>
</ItemInfo>
</ItemInfoList>
I want to change the ItemInfo and ItemInfoList to something more sensible like a business entity name. How can I do that?
As far as I can tell, you can't change these names because the data contracts, ItemInfosList and ItemInfo, are being provided for you by REST kit, so you're giving up some of the control by using CollectionServiceBase.