Xpath selectnodes using VBA - vba

I'm trying to pull sku values out of some XML,
I can't iterate through the XML as I normally do, because due to the way the XML is returned from Ebay, if there is more than on SKU in the order, only the first SKU will be parsed. Therefore, I need a way of trapping those orders which have more than one SKU on the the order (which is simple enough, becuase such orders don't have a hyphen in the OrderID field), but then a command to iterate through the skus for such OrderIDs trapped. Here's the XML (personal data changed)
<?xml version="1.0"?>
<GetOrdersResponse
xmlns="urn:ebay:apis:eBLBaseComponents">
<Timestamp>2016-10-08T17:53:47.349Z</Timestamp>
<Ack>Success</Ack>
<Version>987</Version>
<Build>E987_INTL_APIXO_18127637_R1</Build>
<PaginationResult>
<TotalNumberOfPages>1</TotalNumberOfPages>
<TotalNumberOfEntries>1</TotalNumberOfEntries>
</PaginationResult>
<HasMoreOrders>false</HasMoreOrders>
<OrderArray>
<Order>
<OrderID>214583631017</OrderID>
<OrderStatus>Completed</OrderStatus>
<AdjustmentAmount currencyID="GBP">0.0</AdjustmentAmount>
<AmountPaid currencyID="GBP">23.76</AmountPaid>
<AmountSaved currencyID="GBP">0.0</AmountSaved>
<CheckoutStatus>
<eBayPaymentStatus>NoPaymentFailure</eBayPaymentStatus>
<LastModifiedTime>2016-10-08T14:24:38.000Z</LastModifiedTime>
<PaymentMethod>PayPal</PaymentMethod>
<Status>Complete</Status>
<IntegratedMerchantCreditCardEnabled>false</IntegratedMerchantCreditCardEnabled>
</CheckoutStatus>
<ShippingDetails>
<SalesTax>
<SalesTaxPercent>0.0</SalesTaxPercent>
<SalesTaxState></SalesTaxState>
<ShippingIncludedInTax>false</ShippingIncludedInTax>
<SalesTaxAmount currencyID="GBP">0.0</SalesTaxAmount>
</SalesTax>
<InternationalShippingServiceOption>
<ShippingService>UK_RoyalMailAirmailInternational</ShippingService>
<ShippingServiceCost currencyID="GBP">5.78</ShippingServiceCost>
<ShippingServicePriority>1</ShippingServicePriority>
</InternationalShippingServiceOption>
<SellingManagerSalesRecordNumber>20937</SellingManagerSalesRecordNumber>
<GetItFast>false</GetItFast>
</ShippingDetails>
<CreatingUserRole>Buyer</CreatingUserRole>
<CreatedTime>2016-10-08T14:22:45.000Z</CreatedTime>
<PaymentMethods>CCAccepted</PaymentMethods>
<PaymentMethods>PayPal</PaymentMethods>
<SellerEmail>sales#google.com</SellerEmail>
<ShippingAddress>
<Name>Doy.ssl Garbarina Francesca</Name>
<Street1>Via Goossman,23</Street1>
<Street2></Street2>
<CityName>Rome</CityName>
<StateOrProvince>MI</StateOrProvince>
<Country>IT</Country>
<CountryName>Italy</CountryName>
<Phone>320713385</Phone>
<PostalCode>22119</PostalCode>
<AddressID>1997656621018</AddressID>
<AddressOwner>eBay</AddressOwner>
<ExternalAddressID></ExternalAddressID>
</ShippingAddress>
<ShippingServiceSelected>
<ShippingService>UK_RoyalMailAirmailInternational</ShippingService>
<ShippingServiceCost currencyID="GBP">5.78</ShippingServiceCost>
</ShippingServiceSelected>
<Subtotal currencyID="GBP">17.98</Subtotal>
<Total currencyID="GBP">23.76</Total>
<TransactionArray>
<Transaction>
<Buyer>
<Email>steve#yahootest.it</Email>
<UserFirstName>Ted Alfy</UserFirstName>
<UserLastName>La Guff</UserLastName>
</Buyer>
<ShippingDetails>
<SellingManagerSalesRecordNumber>21935</SellingManagerSalesRecordNumber>
</ShippingDetails>
<CreatedDate>2016-10-08T14:22:45.000Z</CreatedDate>
<Item>
<ItemID>252071330119</ItemID>
<Site>UK</Site>
<Title>T Shirt </Title>
<SKU>ts-001</SKU>
<ConditionID>1000</ConditionID>
<ConditionDisplayName>New</ConditionDisplayName>
</Item>
<QuantityPurchased>1</QuantityPurchased>
<Status>
<PaymentHoldStatus>None</PaymentHoldStatus>
<InquiryStatus>NotApplicable</InquiryStatus>
<ReturnStatus>NotApplicable</ReturnStatus>
</Status>
<TransactionID>1927179184015</TransactionID>
<TransactionPrice currencyID="GBP">7.99</TransactionPrice>
<ShippingServiceSelected>
<ShippingPackageInfo>
<EstimatedDeliveryTimeMin>2016-10-12T22:00:00.000Z</EstimatedDeliveryTimeMin>
<EstimatedDeliveryTimeMax>2016-10-17T22:00:00.000Z</EstimatedDeliveryTimeMax>
</ShippingPackageInfo>
</ShippingServiceSelected>
<TransactionSiteID>Italy</TransactionSiteID>
<Platform>eBay</Platform>
<Taxes>
<TotalTaxAmount currencyID="GBP">0.0</TotalTaxAmount>
<TaxDetails>
<Imposition>SalesTax</Imposition>
<TaxDescription>SalesTax</TaxDescription>
<TaxAmount currencyID="GBP">0.0</TaxAmount>
<TaxOnSubtotalAmount currencyID="GBP">0.0</TaxOnSubtotalAmount>
<TaxOnShippingAmount currencyID="GBP">0.0</TaxOnShippingAmount>
<TaxOnHandlingAmount currencyID="GBP">0.0</TaxOnHandlingAmount>
</TaxDetails>
<TaxDetails>
<Imposition>WasteRecyclingFee</Imposition>
<TaxDescription>ElectronicWasteRecyclingFee</TaxDescription>
<TaxAmount currencyID="GBP">0.0</TaxAmount>
</TaxDetails>
</Taxes>
<OrderLineItemID>252171600110-1928179174015</OrderLineItemID>
<ExtendedOrderID>216483631017!739847967018</ExtendedOrderID>
<eBayPlusTransaction>false</eBayPlusTransaction>
</Transaction>
<Transaction>
<Buyer>
<Email>steve#yahootest.it</Email>
<UserFirstName>Ted Alfy</UserFirstName>
<UserLastName>La Guff</UserLastName>
</Buyer>
<ShippingDetails>
<SellingManagerSalesRecordNumber>21935</SellingManagerSalesRecordNumber>
</ShippingDetails>
<CreatedDate>2016-10-08T14:22:45.000Z</CreatedDate>
<Item>
<ItemID>252072320819</ItemID>
<Site>UK</Site>
<Title>T Shirt </Title>
<SKU>ts-002</SKU>
<ConditionID>1000</ConditionID>
<ConditionDisplayName>New</ConditionDisplayName>
</Item>
<QuantityPurchased>1</QuantityPurchased>
<Status>
<PaymentHoldStatus>None</PaymentHoldStatus>
<InquiryStatus>NotApplicable</InquiryStatus>
<ReturnStatus>NotApplicable</ReturnStatus>
</Status>
<TransactionID>1894939757016</TransactionID>
<TransactionPrice currencyID="GBP">9.99</TransactionPrice>
<ShippingServiceSelected>
<ShippingPackageInfo>
<EstimatedDeliveryTimeMin>2016-10-12T22:00:00.000Z</EstimatedDeliveryTimeMin>
<EstimatedDeliveryTimeMax>2016-10-17T22:00:00.000Z</EstimatedDeliveryTimeMax>
</ShippingPackageInfo>
</ShippingServiceSelected>
<TransactionSiteID>Italy</TransactionSiteID>
<Platform>eBay</Platform>
<Taxes>
<TotalTaxAmount currencyID="GBP">0.0</TotalTaxAmount>
<TaxDetails>
<Imposition>SalesTax</Imposition>
<TaxDescription>SalesTax</TaxDescription>
<TaxAmount currencyID="GBP">0.0</TaxAmount>
<TaxOnSubtotalAmount currencyID="GBP">0.0</TaxOnSubtotalAmount>
<TaxOnShippingAmount currencyID="GBP">0.0</TaxOnShippingAmount>
<TaxOnHandlingAmount currencyID="GBP">0.0</TaxOnHandlingAmount>
</TaxDetails>
<TaxDetails>
<Imposition>WasteRecyclingFee</Imposition>
<TaxDescription>ElectronicWasteRecyclingFee</TaxDescription>
<TaxAmount currencyID="GBP">0.0</TaxAmount>
</TaxDetails>
</Taxes>
<OrderLineItemID>262002331873-1894939957016</OrderLineItemID>
<ExtendedOrderID>216583731017!734847937018</ExtendedOrderID>
<eBayPlusTransaction>false</eBayPlusTransaction>
</Transaction>
</TransactionArray>
<BuyerUserID>xyz123</BuyerUserID>
<PaidTime>2016-10-08T14:22:45.000Z</PaidTime>
<IntegratedMerchantCreditCardEnabled>false</IntegratedMerchantCreditCardEnabled>
<EIASToken>nY+sHZ2PrBmdj6wVyY+sEZ2PrA3dj6wGkYSiAZ2LpASdj6x9nY+seQ==</EIASToken>
<PaymentHoldStatus>None</PaymentHoldStatus>
<IsMultiLegShipping>false</IsMultiLegShipping>
<SellerUserID>pht01</SellerUserID>
<SellerEIASToken>nY+sHZ2PrBmdj6wVneY+sEZ2PrA2dj6wFlIOpDZeApAudj6x9nY+seQ==</SellerEIASToken>
<CancelStatus>NotApplicable</CancelStatus>
<ExtendedOrderID>216589641017!734857936018</ExtendedOrderID>
<ContainseBayPlusTransaction>false</ContainseBayPlusTransaction>
</Order>
</OrderArray>
<OrdersPerPage>100</OrdersPerPage>
<PageNumber>1</PageNumber>
<ReturnedOrderCountActual>8</ReturnedOrderCountActual>
in the above XML, there is one OrderID with two SKUs (normally there are many more orders, but to remove 'noise' I've stripped the XML back to be just one order)....a t-shirt with the SKU ts-001 & another t-shirt with the SKU ts-002 ...As a first step I seek some way of counting how many SKUs there are by the OrderID of 216583631017
Here's my (stripped back) code...
Dim objxmldoc As New MSXML2.DOMDocument60
Dim xmlNamespaces As String
xmlNamespaces = "xmlns:ebay='urn:ebay:apis:eBLBaseComponents'"
objxmldoc.SetProperty "SelectionNamespaces", xmlNamespaces
objxmldoc.SetProperty "SelectionLanguage", "XPath"
If InStr(OrderID, "-") = 0 Then 'if no hyphen in the OrderID, then it's a multi item order...
Set xmlNodes = objxmldoc.selectNodes("//ebay:OrderID[#OrderID='216583631017']")
Debug.Print "Total Number of nodes selected: " & xmlNodes.length ' show how many of the trapped info was counted
end if

You XPath should be:
//ebay:Order[OrderID = '216583631017']
Please note: XPath is case-sensitive.

I don't think this question is still bothering you, and I don't understand exactly what you needed.
You can get all Order nodes from the xml with:
/GetOrdersResponse/OrderArray/Order
And then per Order node you can get all SKU's with:
TransactionArray/Transaction/Item/SKU
Or if you're just interested in all SKU's at once:
//Order/TransactionArray/Transaction/Item/SKU
Or just the Orders that have multiple SKU:
/GetOrdersResponse/OrderArray/Order[count(TransactionArray/Transaction/Item/SKU) gt 1]

Related

PLSQL - REGEXP_SUBSTR Remove XML Tags

I currently have a payload that was generated by oracle xml gateway that I need to pull some exact information out. The payload information is store within a db table meaning that I am attempting to us regexp_substr to accomplish this task.
This is the tag that is in the middle of the XML document
<IDCODE>S2200</IDCODE>
"<?xml version="1.0" encoding="UTF-8" standalone='no'?>
<!DOCTYPE PROCESS_INVOICE_002 SYSTEM "asfasdf.dtd">
<!-- Oracle eXtensible Markup Language Gateway Server -->
<PROCESS_INVOICE_002>
<CNTROLAREA>
<BSR>
<VERB value="PROCESS"/>
<NOUN value="INVOICE"/>
<REVISION value="002"/>
</BSR>
<SENDER>
<LOGICALID/>
<COMPONENT/>
<TASK/>
<REFERENCEID/>
<CONFIRMATION/>
<LANGUAGE/>
<CODEPAGE/>
<AUTHID/>
</SENDER>
<DATETIME qualifier="CREATION">
<YEAR/>
<MONTH/>
<DAY/>
<HOUR/>
<MINUTE/>
<SECOND/>
<SUBSECOND/>
<TIMEZONE/>
</DATETIME>
</CNTROLAREA>
<DATAAREA>
<PROCESS_INVOICE>
<INVHEADER>
<AMOUNT qualifier="DOCUMENT" type="T" index="1">
<VALUE>78538</VALUE>
<NUMOFDEC>8</NUMOFDEC>
<SIGN>+</SIGN>
<CURRENCY>USD</CURRENCY>
<DRCR>D</DRCR>
</AMOUNT>
<DATETIME qualifier="DOCUMENT" index="1">
<YEAR>2020</YEAR>
<MONTH>11</MONTH>
<DAY>28</DAY>
<HOUR>00</HOUR>
<MINUTE>00</MINUTE>
<SECOND>00</SECOND>
<SUBSECOND>0000</SUBSECOND>
<TIMEZONE>+0000</TIMEZONE>
</DATETIME>
<DOCUMENTID>81989184</DOCUMENTID>
<DESCRIPTN/>
<DOCTYPE>INV</DOCTYPE>
<PAYMETHOD/>
<REASONCODE/>
<USERAREA>
<NOTEREFCODE/>
<NOTESREF/>
<VENDNUMQUAL>IA</VENDNUMQUAL>
<VENDNUM>98181</VENDNUM>
<DEPTNUMQUAL>DP</DEPTNUMQUAL>
<DEPTNUM>85</DEPTNUM>
<ORDNUMQUAL/>
<ORDNUM>0</ORDNUM>
<CUSTCODEQUAL/>
<CUSTCODE/>
<NETDAYS/>
<DATETIMEQUAL/>
<FOBCODE/>
<UOM/>
<TOTALQUANTITY/>
</USERAREA>
<PARTNER>
<NAME index="1">COMPANY NAME</NAME>
<ONETIME/>
<PARTNRID/>
<PARTNRTYPE>Supplier</PARTNRTYPE>
<SYNCIND/>
<ACTIVE/>
<CURRENCY/>
<DESCRIPTN/>
<DUNSNUMBER/>
<GLENTITYS/>
<PARENTID/>
<PARTNRIDX/>
<PARTNRRATG/>
<PARTNRROLE/>
<PAYMETHOD/>
<TAXEXEMPT/>
<TAXID/>
<TERMID/>
<USERAREA>
<IDQUAL/>
<IDCODE/>
</USERAREA>
<CONTACT>
<NAME index="1">PROFILE</NAME>
<CONTCTTYPE/>
<DESCRIPTN/>
<EMAIL/>
<FAX index="1"/>
<TELEPHONE index="1"/>
<USERAREA/>
</CONTACT>
</PARTNER>
<PARTNER>
<NAME index="1">CUSTOMER NAME</NAME>
<ONETIME/>
<PARTNRID>981698198</PARTNRID>
<PARTNRTYPE>ShipTo</PARTNRTYPE>
<SYNCIND/>
<ACTIVE/>
<CURRENCY/>
<DESCRIPTN/>
<DUNSNUMBER/>
<GLENTITYS/>
<PARENTID/>
<PARTNRIDX/>
<PARTNRRATG/>
<PARTNRROLE/>
<PAYMETHOD/>
<TAXEXEMPT/>
<TAXID/>
<TERMID/>
<USERAREA>
<IDQUAL>ZZ</IDQUAL>
<IDCODE>S2200</IDCODE>
</USERAREA>
<ADDRESS>
<ADDRLINE index="1">123 MAIN STREET</ADDRLINE>
<ADDRTYPE/>
<CITY>HAM CITY</CITY>
<COUNTRY>United States</COUNTRY>
<COUNTY>NEW YORK</COUNTY>
<DESCRIPTN/>
<FAX index="1"/>
<POSTALCODE>18080</POSTALCODE>
<REGION/>
<STATEPROVN>NY</STATEPROVN>
<TAXJRSDCTN/>
<TELEPHONE index="1"/>
<URL/>
<USERAREA/>
</ADDRESS>
REGEX that I am using in the query
TRIM(regexp_substr(ed.payload, '?.+(</IDCODE>)')) Store_NUM,
TRIM(regexp_substr(ed.payload, '(^IDCODE)?.+(</IDCODE>)')) Store_Number
The Outcome that I am receiving from the above SQL regexp_substr. The issue is that I have made it to the correct tab but I can't figure out how to strip the \<IDCODE> and the \</IDCODE> for the output
-Field can have 4 or 5 chars
-letters or numbers
<IDCODE>S2200</IDCODE> Store_NUM
<IDCODE>S2200</IDCODE> Store_Number
I believe you are looking for this if I am understanding you correctly. Return everything in the group between the tags.
SELECT REGEXP_SUBSTR('<IDCODE>S2200</IDCODE>', '<IDCODE>(.*)</IDCODE>', 1, 1, NULL, 1) Store_Number
from dual;
STORE_NUMBER
------------
S2200
1 row selected.

Extracting XML data using SQL

I would like to be able to extract specific data from a XML type using Oracle in my example for the customer named "Arshad Ali"
This is my xml data that was inserted:
<Customers>
<Customer CustomerName="Arshad Ali" CustomerID="C001">
<Orders>
<Order OrderDate="2012-07-04T00:00:00" OrderID="10248">
<OrderDetail Quantity="5" ProductID="10" />
<OrderDetail Quantity="12" ProductID="11" />
<OrderDetail Quantity="10" ProductID="42" />
</Order>
</Orders>
<Address> Address line 1, 2, 3</Address>
</Customer>
<Customer CustomerName="Paul Henriot" CustomerID="C002">
<Orders>
<Order OrderDate="2011-07-04T00:00:00" OrderID="10245">
<OrderDetail Quantity="12" ProductID="11" />
<OrderDetail Quantity="10" ProductID="42" />
</Order>
</Orders>
<Address> Address line 5, 6, 7</Address>
</Customer>
<Customer CustomerName="Carlos Gonzlez" CustomerID="C003">
<Orders>
<Order OrderDate="2012-08-16T00:00:00" OrderID="10283">
<OrderDetail Quantity="3" ProductID="72" />
</Order>
</Orders>
<Address> Address line 1, 4, 5</Address>
</Customer>
</Customers>
</ROOT>
using get clob I was able to extract all of the customers.
Was wondering if anyone could help me extract data for a specific customer.. tried using the following but was unsuccessful
SELECT extract(OBJECT_VALUE, '/root/Customers') "customer"
FROM mytable2
WHERE existsNode(OBJECT_VALUE, '/customers[CustomerName="Arshad Ali" CustomerID="C001"]')
= 1;
The case and exact names of the XML nodes matter:
SELECT extract(OBJECT_VALUE,
'/ROOT/Customers/Customer[#CustomerName="Arshad Ali"][#CustomerID="C001"]') "customer"
FROM mytable2
WHERE existsnode (OBJECT_VALUE,
'/ROOT/Customers/Customer[#CustomerName="Arshad Ali"][#CustomerID="C001"]') = 1
db<>fiddle
If you only want to search by name then only use that attribute:
SELECT extract(OBJECT_VALUE,
'/ROOT/Customers/Customer[#CustomerName="Arshad Ali"]') "customer"
FROM mytable2
WHERE existsnode (OBJECT_VALUE,
'/ROOT/Customers/Customer[#CustomerName="Arshad Ali"]') = 1
But extract() and existsnode() are deprecated; use xmlquery() and xmlexists() instead:
SELECT xmlquery('/ROOT/Customers/Customer[#CustomerName="Arshad Ali"][#CustomerID="C001"]'
passing object_value
returning content) "customer"
FROM mytable2
WHERE xmlexists('/ROOT/Customers/Customer[#CustomerName="Arshad Ali"][#CustomerID="C001"]'
passing object_value)
db<>fiddle

How to specify / Add tags before the Nested XML on SQL Server

I am trying to bypass C# to build a google shopping feed directly from SQL Server.
This is what I have for the nested XML body.
DECLARE #XMLBODY XML
SET #XMLBODY = (
SELECT
ID as "ID",
title as "title",
link as "link",
[description] as "description",
image_link as "image_link"
,[Price] as "Price"
,[mpn] as "mpn"
,[brand] as "brand"
,[Condition] as "Condition"
,[availability] as "availability"
,[shipping_weight] as "shipping_weight"
,[google_product_category] as "google_product_category"
,[custom_label_0] as "custom_label_0"
,[custom_label_1] as "custom_label_1"
,[custom_label_2] as "custom_label_2"
,[custom_label_3] as "custom_label_3"
,[custom_label_4] as "custom_label_4" FROM dbo.SmartShoppingFeed
FOR XML PATH ('item'))
SELECT #XMLBODY
And as result, I am getting the following XML (only showing first 2..)
<item>
<ID>22760</ID>
<title>76101 - Product Name A</title>
<link>landingpage2.aspx</link>
<description>body spacers</description>
<image_link>productimage_001.jpg</image_link>
<Price>427.6300</Price>
<mpn>76101AA</mpn>
</item>
<item>
<ID>22760</ID>
<title>76101 - Product Name B</title>
<link>landingpage2.aspx</link>
<description>body spacers</description>
<image_link>productimage_002.jpg</image_link>
<Price>427.6300</Price>
<mpn>76102AA</mpn>
</item>
And what I need as final result is the body with schema, version, and NS before the body and closing tag after the body as follow
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title>storename</title>
<link>https://www.storename.com/</link>
<description></description>
<language>en-US</language>
<pubDate>Thu, 25 Jul 2019 20:43:33 GMT</pubDate>
<lastBuildDate>Thu, 25 Jul 2019 20:43:33 GMT</lastBuildDate>
<item>
<ID>22760</ID>
<title>76101 - Product Name A</title>
<link>landingpage2.aspx</link>
<description>body spacers</description>
<image_link>productimage_001.jpg</image_link>
<Price>427.6300</Price>
<mpn>76101AA</mpn>
</item>
<item>
<ID>22760</ID>
<title>76101 - Product Name B</title>
<link>landingpage2.aspx</link>
<description>body spacers</description>
<image_link>productimage_002.jpg</image_link>
<Price>427.6300</Price>
<mpn>76102AA</mpn>
</item>
</channel>
</rss>
I have tried many workarounds to add them statically by casting as string and use concat to combine the head and tail with the body but that didn't work as planned.
Thanks for the help in advance.
You can use XQuery to easily re-shape the final XML as follows:
SQL
DECLARE #XMLBODY XML = '<item>
<ID>22760</ID>
<title>76101 - Product Name A</title>
<link>landingpage2.aspx</link>
<description>body spacers</description>
<image_link>productimage_001.jpg</image_link>
<Price>427.6300</Price>
<mpn>76101AA</mpn>
</item>
<item>
<ID>22760</ID>
<title>76101 - Product Name B</title>
<link>landingpage2.aspx</link>
<description>body spacers</description>
<image_link>productimage_002.jpg</image_link>
<Price>427.6300</Price>
<mpn>76102AA</mpn>a
</item>';
DECLARE #finalXML XML;
SET #finalXML = #XMLBODY.query('<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title>storename</title>
<link>https://www.storename.com/</link>
<description></description>
<language>en-US</language>
<pubDate>Thu, 25 Jul 2019 20:43:33 GMT</pubDate>
<lastBuildDate>Thu, 25 Jul 2019 20:43:33 GMT</lastBuildDate>
{
for $item in /item
return $item
}
</channel>
</rss>
');
SELECT #finalXML;
Strictly speaking, Google product feed requires prefixes so the solution may look like this.
DECLARE #XMLBODY XML
with xmlnamespaces('http://base.google.com/ns/1.0' as g,
'http://base.google.com/cns/1.0' as c)
SELECT #XMLBODY = (
SELECT
ID as "g:ID",
title as "title",
link as "link",
[description] as "description",
image_link as "g:image_link"
,[Price] as "g:price"
,[mpn] as "g:mpn"
,[brand] as "g:brand"
,[Condition] as "g:condition"
,[availability] as "g:availability"
,[shipping_weight] as "g:shipping_weight"
,[google_product_category] as "g:google_product_category"
,[custom_label_0] as "c:custom_label_0"
,[custom_label_1] as "c:custom_label_1"
FROM dbo.SmartShoppingFeed
FOR XML PATH ('item'),root('root'))
SELECT #XMLBODY
And then apply great #Yitzhak Khabinsky's solution.

Find element or attribute value anywhere in XML

I am trying to find the value of an element / attribute regardless of where it exists in the XML.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<cXML payloadID="12345677-12345567" timestamp="2017-07-26T09:11:05">
<Header>
<From>
<Credential domain="1212">
<Identity>01235 </Identity>
<SharedSecret/>
</Credential>
</From>
<To>
<Credential domain="1212">
<Identity>01234</Identity>
</Credential>
</To>
<Sender>
<UserAgent/>
<Credential domain="8989">
<Identity>10678</Identity>
<SharedSecret>Testing123</SharedSecret>
</Credential>
</Sender>
</Header>
<Request deploymentMode="Prod">
<ConfirmationRequest>
<ConfirmationHeader noticeDate="2017-07-26T09:11:05" operation="update" type="detail">
<Total>
<Money>0.00</Money>
</Total>
<Shipping>
<Description>Delivery</Description>
</Shipping>
<Comments>WO# generated</Comments>
</ConfirmationHeader>
<OrderReference orderDate="2017-07-25T15:22:11" orderID="123456780000">
<DocumentReference payloadID="5678-4567"/>
</OrderReference>
<ConfirmationItem quantity="1" lineNumber="1">
<ConfirmationStatus quantity="1" type="detail">
<ItemIn quantity="1">
<ItemID>
<SupplierPartID>R954-89</SupplierPartID>
</ItemID>
<ItemDetail>
<UnitPrice>
<Money currency="USD">0.00</Money>
</UnitPrice>
<Description>Test Descritpion 1</Description>
<UnitOfMeasure>QT</UnitOfMeasure>
</ItemDetail>
</ItemIn>
</ConfirmationStatus>
</ConfirmationItem>
<ConfirmationItem quantity="1" lineNumber="2">
<ConfirmationStatus quantity="1" type="detail">
<ItemIn quantity="1">
<ItemID>
<SupplierPartID>Y954-89</SupplierPartID>
</ItemID>
<ItemDetail>
<UnitPrice>
<Money currency="USD">0.00</Money>
</UnitPrice>
<Description>Test Descritpion 2</Description>
<UnitOfMeasure>QT</UnitOfMeasure>
</ItemDetail>
</ItemIn>
</ConfirmationStatus>
</ConfirmationItem>
</ConfirmationRequest>
</Request>
</cXML>
I want to get the value of the payloadID on the DocumentReference element. This is what I have tried so far:
BEGIN
Declare #Xml xml
Set #Xml = ('..The XML From Above..' as xml)
END
--no value comes back
Select c.value('(/*/DocumentReference/#payloadID)[0]','nvarchar(max)') from #Xml.nodes('//cXML') x(c)
--no value comes back
Select c.value('#payloadID','nvarchar(max)') from #Xml.nodes('/cXML/*/DocumentReference') x(c)
--check if element exists and it does
Select #Xml.exist('//DocumentReference');
I tried this in an xPath editor: //DocumentReference/#payloadID
This does work, but I am not sure what the equivalent syntax is in SQL
Calling .nodes() (like suggested in comment) is an unecessary overhead...
Better try it like this:
SELECT #XML.value('(//DocumentReference/#payloadID)[1]','nvarchar(max)')
And be aware, that XPath starts counting at 1. Your example with [0] cannot work...
--no value comes back
Select c.value('(/*/DocumentReference/#payloadID)[0]','nvarchar(max)') from...

Adding namespace limits results Linq to XML

Ive read a few articles on Linq to XML and either ive picked it up wrong or missing some piece of the puzzle.
What im trying to achieve is to load some XML, get required data by different named fields and nodes/elements. Here is the XML
<?xml version="1.0" encoding="utf-8"?>
<metadata created="2014-05-15T12:26:07.701Z" xmlns="http://site/cu-2.0#" xmlns:ext="http://site/cu/b-2.0">
<customer-list count="47" offset="0">
<customer id="7123456" type="Cust" ext:mark="1">
<name>Tony Watt</name>
<sort-name>Watt, Tony</sort-name>
<gender>male</gender>
<country>US</country>
<knownAs-list>
<knownAs locale="ko" sort-name="Tony Watt"</knownAs>
<knownAs locale="ja" sort-name="Watt Tony"</knownAs>
</knownAs-list>
</customer>
<tag-list>
<tag count="1">
<name>Country</name>
</tag>
<tag count="1">
<name>usa</name>
</tag>
<customer id="9876543" type="Cust" ext:mark="2">
So i can load the XML and i can display data. Heres a snippet of the code
Dim ns As XNamespace = "http://site/cu-2.0#"
Dim XDoc As XDocument = XDocument.Parse(SomeXML)
For Each c As XElement In XDoc.Descendants(ns + "name")
Response.Write(c)
Next
So this displays all the elements with "name". The problem i have here is i want the customer name but not the tag-list country name (see last few lines of the XML)
Ideally i want to return all the details for each customer but adding the namespace limits the me to all the elements with name when i want other data too. If i remove the namespace i get no results returned so im unsure what to do next?
Ive read a ton of articles but i cant seem to work out what needs to be done or if ive gone down the wrong path? Please remember i have tried other methods which i can post if anyone likes but after reading MSDN and other articles i think ive confused myself or missed out a step.
I think you simply want to use
Dim ns As XNamespace = "http://site/cu-2.0#"
Dim XDoc As XDocument = XDocument.Parse(SomeXML)
For Each c As XElement In XDoc.Descendants(ns + "customer")
Response.Write(c.Element(ns + "name").Value)
Next
If you are trying to get name from customer give this a try
Dim xe As XElement =
<customer-list count="47" offset="0">
<customer id="7123456" type="Cust" mark="1">
<name>Tony Watt</name>
<sort-name>Watt, Tony</sort-name>
<gender>male</gender>
<country>US</country>
<knownAs-list>
<knownAs locale="ko" sort-name="Tony Watt"></knownAs>
<knownAs locale="ja" sort-name="Watt Tony"></knownAs>
</knownAs-list>
</customer>
<customer id="1" type="Cust" mark="1">
<name>Fred Flintstone</name>
<sort-name>Flintstone, Fred</sort-name>
<gender>male</gender>
<country>US</country>
<knownAs-list>
<knownAs locale="ko" sort-name="Fred Flintstone"></knownAs>
<knownAs locale="ja" sort-name="Flintstone Fred"></knownAs>
</knownAs-list>
</customer>
<tag-list>
<tag count="1">
<name>Country</name>
</tag>
<tag count="1">
<name>usa</name>
</tag>
</tag-list>
</customer-list>
Dim ie As IEnumerable(Of XElement) = From c As XElement In xe.Elements
Where c.Name.LocalName = "customer"
Select c From n As XElement In c.Elements
Where n.Name.LocalName = "name" Select n
For Each r As XElement In ie
Debug.WriteLine(r.Value)
Next