Combining Oracle xpath expressions - xpath

I'm running xpath on Oracle 11g.
Using the following code i'm trying to select the number element under the application element with #code="A2" or "U2". If no such #code attribute exists then I just want to select the first application element, with or without a #code attribute.
The 2 expressions (2nd one commented out) in the following code work individually for the 2 halves of the problem:
1) Where #code="A2" or "U2"
2) The first application
Can anyone please tell me how to combine these 2 expressions:
WITH et
AS (SELECT XMLType (
'<patent>
<applications>
<application code="U7">
<applicationId>
<number>351149</number>
</applicationId>
</application>
<application>
<applicationId>
<number>54632</number>
</applicationId>
</application>
<application code="A2">
<applicationId>
<number>DM090884</number>
</applicationId>
</application>
</applications>
</patent>
' ) xt
from dual
)
SELECT
ext.*
FROM
et,
XMLTABLE('/patent'
passing et.xt
Columns
APPLICATION_NUMBER VARCHAR (14)
PATH 'applications/application[(#code="A2" or #code="U2" )][1]/applicationId/number'
--PATH ' applications/application[1]/applicationId/number'
) ext

I think the logic can be - return a or return b if there is no a
a | b[not(../a)]
In your case is something as:
applications/
(application[(#code="A2" or #code="U2")] |
application[not(../application[#code="A2" or #code="U2"])])
[1]/applicationId/number
I have splitted the line for readability

Related

Oracle XML Parsing - ORA-19202 and LPX-00601

I am new to XML parsing in oracle, I am getting ORA-19202: Error occurred in XML processing and LPX-00601: Invalid token for below query. Can anyone please help ?
TABLENAME = PARSEXML
COLUMN1('ID') = VARCHAR |COLUMN2('XML') = CLOB
<?xml version="1.0" encoding="UTF-8"?>
<ns4:TSTCLOB xmlns:ns4="http://example.org/test" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<ns4:Rqst>
<ns2:Initiation>
<ns2:InitiationDetail>
<ns3:Channel>WEB</ns3:Channel>
<ns3:Unit>ABCD</ns3:Unit>
</ns2:InitiationDetail>
</ns2:Initiation>
</ns4:Rqst>
</ns4:TSTCLOB>
SELECT ID, EXTRACT(xmltype(XML), '\ns4:TSTCLOB\ns4:Rqst\ns2:Initiation\ns2:InitiationDetail\ns3:Unit') "unit"
FROM PARSEXML WHERE ID = '123'
1) Your example xml is not valid. It is using 4 namespace but only 2 are declared. You have to add this xmlns:ns2="Namespace2" xmlns:ns3="Namespace3"
<ns4:TSTCLOB xmlns:ns4="http://example.org/test" xmlns:ns2="Namespace2" xmlns:ns3="Namespace3" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<ns4:Rqst>
<ns2:Initiation>
<ns2:InitiationDetail>
<ns3:Channel>WEB</ns3:Channel>
<ns3:Unit>ABCD</ns3:Unit>
</ns2:InitiationDetail>
</ns2:Initiation>
</ns4:Rqst>
</ns4:TSTCLOB>
2) In xpath you have to use slash instead of backslash \ -> / = '/ns4:TSTCLOB/ns4:Rqst/ns2:Initiation/ns2:InitiationDetail/ns3:Unit'
3) Extract method has 3 parameters, the last one is namespace string. If your xml is using other namespace except default one you have to specify this in extract method.
Extract(xml, '/ns4:TSTCLOB/ns4:Rqst/ns2:Initiation/ns2:InitiationDetail/ns3:Unit','xmlns:ns4="http://example.org/test" xmlns:ns2="Namespace2" xmlns:ns3="Namespace3" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"')
4*) Extract,ExtractValue are deprecated , you should use xmltable or xmlquery
Try this approach (simplified the XML for testing purpose):
with tmp as(
select
xmltype(to_clob('<?xml version="1.0" encoding="UTF-8"?>
<TSTCLOB>
<Rqst>
<Initiation>
<InitiationDetail>
<Channel>WEB</Channel>
<Unit>ABCD</Unit>
</InitiationDetail>
</Initiation>
</Rqst>
</TSTCLOB>')) tmp_xml
from dual)
select
xml_tbl.Channel,
xml_tbl.Unit
from
tmp,
xmltable(
'/TSTCLOB/Rqst/Initiation/InitiationDetail' passing tmp.tmp_xml
columns
Channel varchar2(6) path 'Channel',
Unit varchar2(6) path 'Unit') xml_tbl

how to read the data from XML with spaces using oracle

I want to read the data from passage_para tag, after passage_para I have 2 spaces before the expression tag and after the expression tag I have one more space, etc. When I use extract function to get the passage_para tag from the XMLTYPE column it is eliminating all the spaces.
<?xml version="1.0" encoding="UTF-8"?> <item> <information number="sdjsadh" > <response_direction delivery_mode="xcs"> <dparagraph>test</dparagraph> </response_direction> </information> <i_content> <stimulus_reference> <passage> <prose style="1"> <passage_para> <expression> <math xmlns="Math" xmlns:xlink="xlink" display="inline" overflow="scroll"> <mr> <mi>z</mi> <mo>></mo> <mn>0</mn> </mr> </math> </expression> </passage_para> </prose> </passage> </stimulus_reference> </i_content> </item>
which I don't want because it is taking out the spaces. The desired output I need is " z > 0 ".
Note: Between the passage_para tag the child nodes may change, they are not going to be the same.

Xquery does not written a result

I have the following Xquery
select email1
from customers,
XMLTABLE(
'$customer/customerinfo/contacts/phone[#type="work"]'
PASSING object_value as "customer"
columns
email1 varchar2(60) path '/emails/email1'
) as x
EMAIL1
------------------------------------------------------------
1 row selected.
When executed on a table of customers of xmltype stored in oracle 12c i do not get any result but a blank .
The xml itself looks something like this
<customerinfo xmlns:ns0="http://posample.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Cid="1000">
<name>Kathy Smith</name>
<addr country="Canada">
<street>5 Rosewood</street>
<city>Toronto</city>
<prov-state>Ontario</prov-state>
<pcode-zip>M6W 1E6</pcode-zip>
</addr>
<contacts>
<phone type="work">416-555-1358</phone>
<emails>
<email1>kathy#stackoverflow.org</email1>
<email2>kathy#stackover.org</email2>
</emails>
<phone type="personal">416-555-1358</phone>
<emails>
<email1>kathy#stackoverflow.org</email1>
<email2>kathy#stackover.org</email2>
</emails>
</contacts>
</customerinfo>
1.I want the output to be kathy#stackoverflow.org.
<emails1/> is no children of <phone/>. This XML format is a little bit broken, as you cannot directly select any "work" email address.
An XPath expression which only matches the first <email1/> node after the "work phone" would be
/customerinfo/contacts/phone[#type="work"]/following-sibling::email1[1]

Oracle JPG metadata xpath from XMLTYPE column

I have a tavle storing photos. With a pl/sql script i extract the image metadata to the exifmetadata xmltype column.
I would like to select the elements one by one, but i always get null back and i don't know what is the issue with my xpath expression.
<exifMetadata xmlns="http://xmlns.oracle.com/ord/meta/exif" xsi:schemaLocation="http://xmlns.oracle.com/ord/meta/exif http://xmlns.oracle.com/ord/meta/exif" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TiffIfd>
<Make tag="271">Apple</Make>
<Model tag="272">iPhone 4S</Model>
<Orientation tag="274">top left</Orientation>
<XResolution tag="282">72.0</XResolution>
<YResolution tag="283">72.0</YResolution>
<ResolutionUnit tag="296">inches</ResolutionUnit>
<Software tag="305">6.0.1</Software>
<DateTime tag="306">2012-11-16T13:31:15</DateTime>
<YCbCrPositioning tag="531">centered</YCbCrPositioning>
</TiffIfd>
<ExifIfd tag="34665">
<ExposureTime tag="33434">0.004405286</ExposureTime>
<FNumber tag="33437">2.4</FNumber>
<ExposureProgram tag="34850">Normal program</ExposureProgram>
<ExifVersion tag="36864">0221</ExifVersion>
<DateTimeOriginal tag="36867">2012-11-16T12:49:58</DateTimeOriginal>
<DateTimeDigitized tag="36868">2012-11-16T12:49:58</DateTimeDigitized>
<ComponentsConfiguration tag="37121">Y</ComponentsConfiguration>
<ShutterSpeedValue tag="37377">7.82697</ShutterSpeedValue>
<ApertureValue tag="37378">2.5260692</ApertureValue>
<BrightnessValue tag="37379">6.641153</BrightnessValue>
<MeteringMode tag="37383">Pattern</MeteringMode>
<Flash tag="37385">
<Fired>No</Fired>
</Flash>
<FocalLength tag="37386">4.28</FocalLength>
<FlashpixVersion tag="40960">0100</FlashpixVersion>
<ColorSpace tag="40961">sRGB</ColorSpace>
<PixelXDimension tag="40962">2902</PixelXDimension>
<PixelYDimension tag="40963">1938</PixelYDimension>
<SensingMethod tag="41495">One-chip color area</SensingMethod>
<ExposureMode tag="41986">Auto exposure</ExposureMode>
<WhiteBalance tag="41987">Auto</WhiteBalance>
<FocalLengthIn35mmFilm tag="41989">35</FocalLengthIn35mmFilm>
<SceneCaptureType tag="41990">Standard</SceneCaptureType>
</ExifIfd>
</exifMetadata>
And the SQL:
SELECT
p.metaexif.extract('//exifMetadata/TiffIfd/Make/text()').getStringVal() "Model"
FROM scott.photos p
WHERE id=22
;
The id 22 record exist that is sure.
you have a default namespace set so you have to cope with this.
eg use this:
select extractvalue(p.metaexif,'/exifMetadata/TiffIfd/Make',
'xmlns="http://xmlns.oracle.com/ord/meta/exif"')

How to return multiple results with XMLTABLE?

I want to do a query in Oracle using xmltable.
Everything works fine, but there are multiple (n) results for xml node "article_title". For each row the result "<string>Article Name1</string><string>Article Name 2</string>... is returned. But I want every article name to be returned as a single row.
How can I realize this?
SELECT
X.*
FROM
myTable C,
xmltable (
'$cust//member' PASSING C.STAT_XML as "cust"
COLUMNS
name VARCHAR(25) PATH '/member/name',
article_title XMLTYPE PATH '//string/text()'
) as X
WHERE X.name = 'articles';
I'm having a problem with this as well. I have an XML that's supposed to send shipment data from our warehouse management system back to our order management system, and it has various different things that have multiples. The entire XML message has a single ShipConfirmHeader section, so that's easy enough to pull out. Where I run into trouble is that it has a ShipConfirmDetail/Orders section, and there could be any number of orders listed. Within each order, there could be any number of order lines. I can pull the ShipConfirmHeader and the ShipConfirmDetail/Orders together OR I can pull the ShipConfirmHeader and the ShipConfirmDetail/Orders/OrderLineItem together, but when I try pulling the Orders together with the OrderLineItem, there's no way that I can see to join those, so I end up with a cartesian product. To complicate matters even more, each Order could have many Cartons associated with it, and each Carton could contain multiple OrderLineItems, and each Carton could have multiple CartonDetails.
I've included a sample of my XML below. In this example, there's only one Order, one OrderLine, and one Carton (called an LPN in the XML), because I've stripped out all the others (the original XML is over 4000 lines long).
Pulling stuff from the ShipConfirmHeader is relatively easy, like this:
xmltable('/tXML/Message/ShipConfirm/ShipConfirmSummary/ShipConfirmHeaderInfo/'
passing xmltype(msg_xml.full_xml)
columns
invoice_batch varchar2(20) path 'InvcBatchNbr'
) sc_hdr
But when I want to include any of the multiples, it gives me problems. I've tried a variety of things:
-- This gives the error "ORA-22950: cannot ORDER objects without MAP or ORDER method"
xmltable('/tXML/Message/ShipConfirm'
passing xmltype(msg_xml.full_xml)
columns
invoice_batch varchar2(20) path 'ShipConfirmSummary/ShipConfirmHeaderInfo/InvcBatchNbr',
order_dtl xmltype path 'ShipConfirmDetails/Orders'
) sc_hdr
-- This doesn't like the "../" in the XPATH
xmltable('/tXML/Message/ShipConfirm/ShipConfirmDetails/Orders/OrderLineItem'
passing xmltype(msg_xml.full_xml)
columns
invoice_batch varchar2(20) path '../../../ShipConfirmSummary/ShipConfirmHeaderInfo/InvcBatchNbr',
order_id varchar2(20) path '../TcOrderId',
order_line_id varchar2(20) path 'TcOrderLineId',
item_name varchar2(20) path 'ItemName'
) sc_hdr
-- This gives a cartesian product.
xmltable('/tXML/Message/ShipConfirm/ShipConfirmSummary/ShipConfirmHeaderInfo'
passing xmltype(msg_xml.full_xml)
columns
invoice_batch varchar2(20) path 'InvcBatchNbr'
) sc_hdr,
xmltable('/tXML/Message/ShipConfirm/ShipConfirmDetails/Orders'
passing xmltype(msg_xml.full_xml)
columns
order_id varchar2(20) path 'TcOrderId'
) sc_ord_hdr,
xmltable('/tXML/Message/ShipConfirm/ShipConfirmDetails/Orders/OrderLineItem'
passing xmltype(msg_xml.full_xml)
columns
order_line_id varchar2(20) path 'TcOrderLineId',
item_name varchar2(20) path 'ItemName'
) sc_ord_dtl
Here's the sample XML:
<?xml version="1.0" encoding="UTF-8"?>
<tXML>
<Header>
<Source>warehouse management system</Source>
<Action_Type></Action_Type>
<Sequence_Number></Sequence_Number>
<Batch_ID></Batch_ID>
<Reference_ID></Reference_ID>
<User_ID>CRONUSER</User_ID>
<Password></Password>
<Message_Type>ShipConfirm</Message_Type>
<Company_ID>1</Company_ID>
<Msg_Locale>English (United States)</Msg_Locale>
<Msg_Time_Zone>America/Denver</Msg_Time_Zone>
<Version>2018</Version>
</Header>
<Message>
<ShipConfirm>
<ShipConfirmSummary>
<CompanyName>Blah</CompanyName>
<FacilityName>Blah</FacilityName>
<ShipConfirmHeaderInfo>
<InvcBatchNbr>123456</InvcBatchNbr>
<LastInvcDttm>5/27/21 05:45</LastInvcDttm>
<ShippedDttm>5/27/21 05:45</ShippedDttm>
<DateCreated>5/27/21 05:45</DateCreated>
<StoreNbr></StoreNbr>
<ShipVia>ST</ShipVia>
<SchedDeliveryDate></SchedDeliveryDate>
<ProNbr></ProNbr>
<AppointmentNbr></AppointmentNbr>
<ManifestNbr></ManifestNbr>
<SealNbr></SealNbr>
<AppointmentDate></AppointmentDate>
<PartialShipConfirmStatus>5</PartialShipConfirmStatus>
<PreBillStatus>0</PreBillStatus>
<ApptMadeByID></ApptMadeByID>
<BillOfLading></BillOfLading>
<CancelQuantity>0.0</CancelQuantity>
<NbrOfLpns>26</NbrOfLpns>
<NbrOfPlts>0</NbrOfPlts>
<NbrOfOrders>26</NbrOfOrders>
<TotalWt>61.72</TotalWt>
<UserID>USER</UserID>
</ShipConfirmHeaderInfo>
</ShipConfirmSummary>
<ShipConfirmDetails>
<Orders>
<BatchCtrlNbr>123456</BatchCtrlNbr>
<DistributionShipVia>ST</DistributionShipVia>
<DoType>Customer Order</DoType>
<DsgShipVia>ST</DsgShipVia>
<OriginalShipVia>ST</OriginalShipVia>
<IncotermLocAvaTimeZoneId>America/New_York</IncotermLocAvaTimeZoneId>
<InvcBatchNbr>123456</InvcBatchNbr>
<IsBackOrdered>1</IsBackOrdered>
<MajorOrderCtrlNbr></MajorOrderCtrlNbr>
<OrderType>ECOMM_ORDER</OrderType>
<ShipDate>5/27/21 05:45</ShipDate>
<OrderStatus>Unplanned</OrderStatus>
<DoStatus>Shipped</DoStatus>
<TcCompanyId>1</TcCompanyId>
<TcOrderId>MYORDERID</TcOrderId>
<TotalNbrOfLpn>1</TotalNbrOfLpn>
<TotalNbrOfPlt>0</TotalNbrOfPlt>
<TotalNbrOfUnits>1</TotalNbrOfUnits>
<LineHaulShipVia>ST</LineHaulShipVia>
<PartialShipConfirmStatus>5</PartialShipConfirmStatus>
<PreBillStatus>0</PreBillStatus>
<OrderBillToInfo>
<BillToAddress1>Snip</BillToAddress1>
<BillToAddress2></BillToAddress2>
<BillToAddress3></BillToAddress3>
<BillToCity>Snip</BillToCity>
<BillToContact></BillToContact>
<BillToContactName></BillToContactName>
<BillToCountryCode>CA</BillToCountryCode>
<BillToCounty></BillToCounty>
<BillToFacilityName></BillToFacilityName>
<BillToName>Snip</BillToName>
<BillToPhoneNumber>Snip</BillToPhoneNumber>
<BillToPostalCode>Snip</BillToPostalCode>
<BillToStateProv>ON</BillToStateProv>
</OrderBillToInfo>
<OrderDestInfo>
<DestAddress1>Snip</DestAddress1>
<DestAddress2></DestAddress2>
<DestAddress3></DestAddress3>
<DestCity>Snip</DestCity>
<DestContact>Snip</DestContact>
<DestCountryCode>CA</DestCountryCode>
<DestCounty></DestCounty>
<DestDockDoorId>0</DestDockDoorId>
<DestFacilityAliasId></DestFacilityAliasId>
<DestFacilityId>0</DestFacilityId>
<DestFacilityName></DestFacilityName>
<DestName>Snip</DestName>
<DestPhoneNumber>Snip</DestPhoneNumber>
<DestPostalCode>Snip</DestPostalCode>
<DestStateProv>ON</DestStateProv>
</OrderDestInfo>
<OrderOriginInfo>
<OriginAddress1>Snip</OriginAddress1>
<OriginAddress2></OriginAddress2>
<OriginAddress3></OriginAddress3>
<OriginCity>Snip</OriginCity>
<OriginContact></OriginContact>
<OriginCountryCode>CA</OriginCountryCode>
<OriginFacilityAliasId>Snip</OriginFacilityAliasId>
<OriginFacilityId>1</OriginFacilityId>
<OriginFacilityName>Snip</OriginFacilityName>
<OriginPhoneNumber></OriginPhoneNumber>
<OriginPostalCode>Snip</OriginPostalCode>
<OriginStateProv>AB</OriginStateProv>
</OrderOriginInfo>
<OrderInfoFields>
<SplInstrCode1>MW</SplInstrCode1>
<SplInstrCode2>MW</SplInstrCode2>
</OrderInfoFields>
<OrderLineItem>
<InvcBatchNbr>123456</InvcBatchNbr>
<ItemId>159331</ItemId>
<ItemName>MYITEMNAME</ItemName>
<LineItemId>12053970</LineItemId>
<OrderQty>1</OrderQty>
<OrderQtyUom>Unit</OrderQtyUom>
<OrigItemId>159331</OrigItemId>
<OrigItemName>MYITEMNAME</OrigItemName>
<OrigOrderLineItemId>1</OrigOrderLineItemId>
<OrigOrderQty>1</OrigOrderQty>
<OrigOrderQtyUom>Unit</OrigOrderQtyUom>
<OutptOrderLineItemId>3782033</OutptOrderLineItemId>
<Price>15.39</Price>
<PriceTktType></PriceTktType>
<RetailPrice>0.0</RetailPrice>
<ShippedQty>1</ShippedQty>
<TcCompanyId>1</TcCompanyId>
<TcOrderLineId>1</TcOrderLineId>
<UnitVol>0.0744</UnitVol>
<UnitWt>0.58</UnitWt>
<Uom>Unit</Uom>
<UserCanceledQty>0</UserCanceledQty>
<OrderLineItemDefn>
<ItemStyle>Snip</ItemStyle>
<ItemStyleSfx>Snip</ItemStyleSfx>
</OrderLineItemDefn>
</OrderLineItem>
<Lpn>
<BillOfLadingNumber></BillOfLadingNumber>
<CFacilityAliasId>Snip</CFacilityAliasId>
<EstimatedWeight>0.58</EstimatedWeight>
<FinalDestFacilityAliasId></FinalDestFacilityAliasId>
<InvcBatchNbr>123456</InvcBatchNbr>
<LoadedDttm></LoadedDttm>
<ManifestNbr></ManifestNbr>
<MasterBolNbr></MasterBolNbr>
<NonInventoryLpnFlag>0</NonInventoryLpnFlag>
<NonMachineable></NonMachineable>
<OutptLpnId>730888</OutptLpnId>
<PackerUserid>USER</PackerUserid>
<ProcDttm>5/27/21 05:45</ProcDttm>
<ProcStatCode>0</ProcStatCode>
<QtyUom>Unit</QtyUom>
<ServiceLevel></ServiceLevel>
<ShipVia>ST</ShipVia>
<ShippedDttm>5/27/21 05:45</ShippedDttm>
<StaticRouteId></StaticRouteId>
<TcCompanyId>1</TcCompanyId>
<TcLpnId>98765</TcLpnId>
<TcOrderId>Snip</TcOrderId>
<TcParentLpnId></TcParentLpnId>
<TcShipmentId></TcShipmentId>
<TotalLpnQty>1</TotalLpnQty>
<TrackingNbr>Snip</TrackingNbr>
<VolumeUom>cu ft</VolumeUom>
<Weight>0.58</Weight>
<WeightUom>Lbs</WeightUom>
<LoadSequence>0</LoadSequence>
<oLPNXRefNbr></oLPNXRefNbr>
<LpnDetail>
<InvcBatchNbr>123456</InvcBatchNbr>
<ItemId>159331</ItemId>
<ItemName>MYITEMNAME</ItemName>
<LpnDetailId>20153787</LpnDetailId>
<OutptLpnDetailId>3689518</OutptLpnDetailId>
<QtyUom>Unit</QtyUom>
<SizeValue>1</SizeValue>
<TcCompanyId>1</TcCompanyId>
<TcLpnId>98765</TcLpnId>
<DistroNumber></DistroNumber>
<TcOrderLineId>1</TcOrderLineId>
<MinorOrderNbr>Snip</MinorOrderNbr>
<MinorPoNbr></MinorPoNbr>
</LpnDetail>
</Lpn>
</Orders>
</ShipConfirmDetails>
</ShipConfirm>
</Message>
</tXML>
Try something like this:
SELECT X.*
FROM my_table C,
xmltable('for $i in $cust//string , $j in $cust//member[./string=$i]/name return <member>{$j}{$i}</member>'
passing c.stat_xml AS "cust"
columns name varchar2(25) path '/member/name',
article_title xmltype path '//string') AS X
WHERE X.name = 'articles';
Here is a fiddle
I assumed that for every member you have one name but might have many strings

Resources