Modify a portion of an XML with key/value structure - sql-server

I need to write a SQL Server query to change the values of the following example XML, each one should have a different new value:
Example:
From
<Item>
<key>RabbitMQConnection</key>
<value Tr="PropertyBag">
<Item>
<key>Encoding</key>
<value>65001</value>
</Item>
<Item>
<key>HostName</key>
<value>TESTHOST</value>
</Item>
<Item>
<key>UserName</key>
<value>USER</value>
</Item>
<Item>
<key>Password</key>
<value>PASS</value>
</Item>
<Item>
<key>QueueName</key>
<value>TESTQUEUE</value>
</Item>
<Item>
<key>VirtualHost</key>
<value>TESTVHOST</value>
</Item>
</value>
</Item>
<Item>
to
<Item>
<key>RabbitMQConnection</key>
<value Tr="PropertyBag">
<Item>
<key>Encoding</key>
<value>65001</value>
</Item>
<Item>
<key>HostName</key>
<value>TESTHOST22</value>
</Item>
<Item>
<key>UserName</key>
<value>USER222</value>
</Item>
<Item>
<key>Password</key>
<value>PASS22</value>
</Item>
<Item>
<key>QueueName</key>
<value>TESTQUEUE22</value>
</Item>
<Item>
<key>VirtualHost</key>
<value>TESTVHOST22</value>
</Item>
</value>
</Item>
<Item>
I'm really struggling with xpath language, can I get some help please?
Many thanks!

Please try the following.
You can modify the rest of the XML elements one by one by using the same approach.
SQL
DECLARE #xml XML =
N'<Item>
<key>RabbitMQConnection</key>
<value Tr="PropertyBag">
<Item>
<key>Encoding</key>
<value>65001</value>
</Item>
<Item>
<key>HostName</key>
<value>TESTHOST</value>
</Item>
<Item>
<key>UserName</key>
<value>USER</value>
</Item>
<Item>
<key>Password</key>
<value>PASS</value>
</Item>
<Item>
<key>QueueName</key>
<value>TESTQUEUE</value>
</Item>
<Item>
<key>VirtualHost</key>
<value>TESTVHOST</value>
</Item>
</value>
</Item>';
DECLARE #HostName NVARCHAR(30) = 'NewTESTHOST';
SET #xml.modify('replace value of (/Item/value/Item[key="HostName"]/value/text())[1]
with (sql:variable("#HostName"))' );
-- test
SELECT #xml;

Related

I can't delete empty containers in an xml document on SQL Server, such as "<Item />"

I started working for the first time and I don't know much yet, I've been suffering with this problem for two days.
I have a document of this type:
<Tables>
<dbo.ES_Connection_Modes>
<Item />
</dbo.ES_Connection_Modes>
<dbo.ES_Device_Categories>
<Item>
<LINK>1</LINK>
<F_Class>1</F_Class>
<N_Code>1</N_Code>
<B_Default>1</B_Default>
<B_Meter>1</B_Meter>
<B_Tranf>0</B_Tranf>
<B_Regist>0</B_Regist>
<B_Show_InMenu>1</B_Show_InMenu>
<N_Project>-1</N_Project>
<C_Const>EDC_Meter</C_Const>
</Item>
</dbo.ES_Device_Categories>
<dbo.ES_Indicating_Device_Types>
<Item />
</dbo.ES_Indicating_Device_Types>
<dbo.ES_Operating_Principles>
<Item />
</dbo.ES_Operating_Principles>
<dbo.ES_Precission_Classes>
<Item>
<LINK>7</LINK>
<N_Project>687783</N_Project>
<C_Name>2,0</C_Name>
<C_Const>EPC_20</C_Const>
</Item>
<Item>
<LINK>8</LINK>
<N_Project>687783</N_Project>
<C_Name>2,5</C_Name>
<C_Const>EPC_25</C_Const>
</Item>
</dbo.ES_Precission_Classes>
<dbo.ES_Granularity>
<Item />
</dbo.ES_Granularity>
</Tables>
I need to delete the empty item containers and the container containing it to get a document of the following type:
<Tables>
<dbo.ES_Device_Categories>
<Item>
<LINK>1</LINK>
<F_Class>1</F_Class>
<N_Code>1</N_Code>
<B_Default>1</B_Default>
<B_Meter>1</B_Meter>
<B_Tranf>0</B_Tranf>
<B_Regist>0</B_Regist>
<B_Show_InMenu>1</B_Show_InMenu>
<N_Project>-1</N_Project>
<C_Const>EDC_Meter</C_Const>
</Item>
</dbo.ES_Device_Categories>
<dbo.ES_Precission_Classes>
<Item>
<LINK>7</LINK>
<N_Project>687783</N_Project>
<C_Name>2,0</C_Name>
<C_Const>EPC_20</C_Const>
</Item>
<Item>
<LINK>8</LINK>
<N_Project>687783</N_Project>
<C_Name>2,5</C_Name>
<C_Const>EPC_25</C_Const>
</Item>
</dbo.ES_Precission_Classes>
</Tables>
I've tried a lot of things, deleted them, but here's the way I was hoping for, but I get an error:
SET #myDoc.modify('delete /Tables/*[contains(name(), "null")]');
Please try the following solution.
It is deleting 2nd level XML elements under the root (Tables) that have in turn Item elements without children.
SQL
DECLARE #myDoc XML =
N'<Tables>
<dbo.ES_Connection_Modes>
<Item/>
</dbo.ES_Connection_Modes>
<dbo.ES_Device_Categories>
<Item>
<LINK>1</LINK>
<F_Class>1</F_Class>
<N_Code>1</N_Code>
<B_Default>1</B_Default>
<B_Meter>1</B_Meter>
<B_Tranf>0</B_Tranf>
<B_Regist>0</B_Regist>
<B_Show_InMenu>1</B_Show_InMenu>
<N_Project>-1</N_Project>
<C_Const>EDC_Meter</C_Const>
</Item>
</dbo.ES_Device_Categories>
<dbo.ES_Indicating_Device_Types>
<Item/>
</dbo.ES_Indicating_Device_Types>
<dbo.ES_Operating_Principles>
<Item/>
</dbo.ES_Operating_Principles>
<dbo.ES_Precission_Classes>
<Item>
<LINK>7</LINK>
<N_Project>687783</N_Project>
<C_Name>2,0</C_Name>
<C_Const>EPC_20</C_Const>
</Item>
<Item>
<LINK>8</LINK>
<N_Project>687783</N_Project>
<C_Name>2,5</C_Name>
<C_Const>EPC_25</C_Const>
</Item>
</dbo.ES_Precission_Classes>
<dbo.ES_Granularity>
<Item/>
</dbo.ES_Granularity>
</Tables>';
SET #myDoc.modify('delete /Tables/*[not(Item/*)]');
-- test
SELECT #myDoc;

Material UI grid with IntputLabel and Input placed in horizontal row: how to ask vertical-align to be middle for the label?

I have pretty standard React Material UI grid with InputLabel's and Input's placed in horizontal row. The code is:
const Container = (props) => <Grid container {...props} />;
const Item = (props) => <Grid item xs={1} {...props} />;
const ContainerItem = (props) => <Grid container item {...props} />;
function App() {
return (
<div>
<MuiThemeProvider theme={ucs_theme}>
<Container>
<ContainerItem>
<Item>
<InputLabel htmlFor="m_gen_ref_serie">Serie</InputLabel>
</Item>
<Item>
<Input type="text" id="m_gen_ref_serie" />
</Item>
<Item>
<InputLabel htmlFor="m_gen_ref_serie2">Serie 2</InputLabel>
</Item>
<Item>
<Input type="text" id="m_gen_ref_serie2" />
</Item>
<Item>
<InputLabel htmlFor="m_gen_ref_serie3">Serie 3</InputLabel>
</Item>
<Item>
<Input type="text" id="m_gen_ref_serie3" />
</Item>
</ContainerItem>
<ContainerItem>
<Item>
<InputLabel htmlFor="m_gen_ref_serie">Serie</InputLabel>
</Item>
<Item>
<Input type="text" id="m_gen_ref_serie" />
</Item>
<Item>
<InputLabel htmlFor="m_gen_ref_serie2">Serie 2</InputLabel>
</Item>
<Item>
<Input type="text" id="m_gen_ref_serie2" />
</Item>
<Item>
<InputLabel htmlFor="m_gen_ref_serie3">Serie 3</InputLabel>
</Item>
<Item>
<Input type="text" id="m_gen_ref_serie3" />
</Item>
</ContainerItem>
</Container>
</MuiThemeProvider>
</div>
);
}
And full example is available:
https://codesandbox.io/s/react-final-form-material-ui-example-forked-f0ir9?file=/src/index.js
Be aware, that my codesandbox example uses some theming, but the problem is not affected (not solved) by this theming (at least by this kind of theming).
I have problems and my question is about the placement of the InputLabel (rendered as HTML label) text - it is placed left-top. The left-placement is OK. The problem is that I don't like that the text is placed as top (some console entries who some strange margin-bottom). I would like to set vertical-align="middle" for this text. But there is not such property for InputLabel. How can achieve vertical-align="middle" effect for my labels (text of the labeld) in the Material UI grid?
Maybe I have to use some strange intermediate components like Paper?
You can edit your items alignment by using the props alignItems
<Grid container justify='center|flexStart|flexEnd|...' alignItems='center|end|start|....' alignContent='center|....' ...props >
Just look at the documentation here for more informations, you can also use CSS rules on your Grid item to edit the placement

How to extract values from a xml request body with values in an array in wiremock

I am trying to extract line-item value from the below request body into my response in wiremock.
Request:
**<request>
<lineItem>
<item>
<name> name </name>
<quantity> 12 </quantity>
<type>type</type>
</item>
</ lineItem>
<lineItem>
<item>
<name> name2 </name>
<quantity> 10 </quantity>
<type>type2</type>
</item>
</ lineItem>
</request>**
Expected Response:
**<response>
<lineItem>
<item>
<name> name </name>
<quantity> 12 </quantity>
<type>type</type>
</item>
</ lineItem>
<lineItem>
<item>
<name> name2 </name>
<quantity> 10 </quantity>
<type>type2</type>
</item>
</ lineItem>
</response>**
I tried something like this:
<response>
{{#each (xPath request.body '/lineItem/item ') as |element| }}
<lineItem>
<item>
<quantity> (xPath request.body '//lineItem/item/quantity/text()'}}</quantity>
</item>
</ lineItem>
</response>
but for 2 different lineItem in request (as given above), I got 3 lineItem values in response and always getting the first item values in all the 3 lineItems:
Response I got:
**<response>
<lineItem>
<item>
<quantity> 12 </quantity>
</item>
</ lineItem>
<lineItem>
<item>
<quantity> 12 </quantity>
</item>
</ lineItem>
<lineItem>
<item>
<quantity> 12 </quantity>
</item>
</ lineItem>
</response>**
Can someone help me with this scenario?

Amazon Order Fulfillment with Multiple Packages for one Order _POST_ORDER_FULFILLMENT_DATA_

I have been dealing with a problem that pops up once a day. An order with multiple packages (fulfillmentdata,item). This is an order where the person may have ordered two different items and they were sent by the merchant in two different packages with different tracking numbers. Tends to be uncommon on amazon but very common in other systems.
I have tried multiple versions of the XML to try and make this work but to no success.
My first attempt:
<AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
<Header>
<DocumentVersion>1.01</DocumentVersion>
<MerchantIdentifier>XXXXXXXX</MerchantIdentifier>
</Header>
<MessageType>OrderFulfillment</MessageType>
<Message>
<MessageID>1</MessageID>
<OrderFulfillment>
<MerchantOrderID>55XXXX</MerchantOrderID>
<FulfillmentDate>2018-10-01T17:XX:XX-00:00</FulfillmentDate>
<FulfillmentData>
<CarrierCode>USPS</CarrierCode>
<ShippingMethod>First Class Parcel</ShippingMethod>
<ShipperTrackingNumber>940011590109XXXXXX</ShipperTrackingNumber>
</FulfillmentData>
<FulfillmentData>
<CarrierCode>USPS</CarrierCode>
<ShippingMethod>First Class Parcel</ShippingMethod>
<ShipperTrackingNumber>940011590109XXXXX</ShipperTrackingNumber>
</FulfillmentData>
<Item>
<AmazonOrderItemCode>354178450XXXX</AmazonOrderItemCode>
<Quantity>1</Quantity>
</Item>
<Item>
<AmazonOrderItemCode>014909917XXXX</AmazonOrderItemCode>
<Quantity>1</Quantity>
</Item>
</OrderFulfillment>
</Message>
</AmazonEnvelope>
Next I tried to split it up into two different messages
<AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
<Header>
<DocumentVersion>1.01</DocumentVersion>
<MerchantIdentifier>XXXXXXXX</MerchantIdentifier>
</Header>
<MessageType>OrderFulfillment</MessageType>
<Message>
<MessageID>1</MessageID>
<OrderFulfillment>
<MerchantOrderID>554XXX</MerchantOrderID>
<FulfillmentDate>2018-10-01T17:XX:XX-00:00</FulfillmentDate>
<FulfillmentData>
<CarrierCode>USPS</CarrierCode>
<ShippingMethod>First Class Parcel</ShippingMethod>
<ShipperTrackingNumber>94001159010920XX</ShipperTrackingNumber>
</FulfillmentData>
<Item>
<AmazonOrderItemCode>0149099174XXXX</AmazonOrderItemCode>
<Quantity>1</Quantity>
</Item>
</OrderFulfillment>
</Message>
<Message>
<MessageID>2</MessageID>
<OrderFulfillment>
<MerchantOrderID>554XXX</MerchantOrderID>
<FulfillmentDate>2018-10-01T17:XX:XX-00:00</FulfillmentDate>
<FulfillmentData>
<CarrierCode>USPS</CarrierCode>
<ShippingMethod>First Class Parcel</ShippingMethod>
<ShipperTrackingNumber>9400115901092029XXX</ShipperTrackingNumber>
</FulfillmentData>
<Item>
<AmazonOrderItemCode>3541784506XXXX</AmazonOrderItemCode>
<Quantity>1</Quantity>
</Item>
</OrderFulfillment>
</Message>
</AmazonEnvelope>
With the second message I received the following error (for both message 1 and 2):
<MessageID>2</MessageID>
<ResultCode>Error</ResultCode>
<ResultMessageCode>18028</ResultMessageCode>
<ResultDescription>The data you submitted is incomplete or invalid. For help fixing this, see http://sellercentral.amazon.com/gp/help/30721</ResultDescription>

Empty results when filtering based on position in XQuery

I tried to print the details of 3rd and 4th products in the catalog, but I am getting empty results.
XML input:
<catalog>
<product dept="WMN">
<number>557</number>
<name language="en">Fleece Pullover</name>
<colorChoices>navy black</colorChoices>
</product>
<product dept="ACC">
<number>563</number>
<name language="en">Floppy Sun Hat</name>
</product>
<product dept="ACC">
<number>443</number>
<name language="en">Deluxe Travel Bag</name>
</product>
<product dept="MEN">
<number>784</number>
<name language="en">Cotton Dress Shirt</name>
<colorChoices>white gray</colorChoices>
<desc>Our <i>favorite</i> shirt!</desc>
</product>
</catalog>
what I tried:
SELECT xDoc.query(' for $prod in //product
let $x:=$prod
return (<Item>{data($x[3])}{data($x[4])}</Item>)')
FROM AdminDocs
where id=6
Output displayed:
<Item />
<Item />
<Item />
<Item />
This defines a loop over all products:
for $prod in //product
For each of those products, you return the third and fourth node out of a sequence of a single product, which obviously will yield empty nodes:
let $x:=$prod
return (<Item>{data($x[3])}{data($x[4])}</Item>)
For a better understanding, return the whole product node each time:
for $prod in //product
return <item>{ $prod }</item>
Which will result in something like this:
<item>
<product dept="WMN">
<number>557</number>
<name language="en">Fleece Pullover</name>
<colorChoices>navy black</colorChoices>
</product>
</item>
<item>
<product dept="ACC">
<number>563</number>
<name language="en">Floppy Sun Hat</name>
</product>
</item>
<item>
<product dept="ACC">
<number>443</number>
<name language="en">Deluxe Travel Bag</name>
</product>
</item>
<item>
<product dept="MEN">
<number>784</number>
<name language="en">Cotton Dress Shirt</name>
<colorChoices>white gray</colorChoices>
<desc>Our <i>favorite</i> shirt!</desc>
</product>
</item>
And each of those <product/> elements being a $prod[1]. Try:
for $prod in //product
return <item>{ $prod[1] }</item>
which will return the exactly same result, compared to
for $prod in //product
return <item>{ $prod[2] }</item>
(or any other positional predicate) resulting in empty <item/> nodes.
Finally, to return only the third and fourth products, shift the positional predicate into the for loop argument:
for $prod in //product[position() = 3 or position() = 4]
return <item>{ $prod }</item>
(and apply data(...) as needed, but I'd guess it won't yield the results you expect here).

Resources