bpws:getVariableData() causes fault if no xpath match is found - oracle

I wanted to use "bpws:getVariableData()" to assign a value only if the xpath expression find a match. If not, nothing should happen. Unfortunately the bpel processing stops with a fault, if the xpath expression finds no match. Is there a way to achieve this behavior?
Thanks for your help.

I found that the oracle BPEL engine provides a feature to ignore missing from data. This Flag can be added to the copy element as follows:
<copy bpelx:ignoreMissingFromData="yes|no"/>
More info on how to set it in the JDeveloper: http://download.oracle.com/docs/cd/E17904_01/integration.1111/e10224/bp_manipdoc.htm#SOASE87087
This solves the problem with the fault message that is thrown. However it still does not show the wanted behavior. My intension was that no assignment is done, if the xpath expression cannot be evaluated. Using the bpelx:ignoreMissingFromData flag however assigns the empty string "" to the target.
In my use case I want to merge tow XML documents. I want to assign a new value to an element in document1 only if the element shows up in document2. If not, leave the element in document1 unchanged.
I solved the problem using a transformation instead of a BPEL assign. In the xsl I use the following statement. The transformation gets two XML documents a input. Document1 is referenced via the parameter $parameter_referenceDocument1.
<elementName>
<xsl:if test="xpathInDocument2">
<xsl:value-of select="xpathInDocument2"/>
</xsl:if>
<xsl:if test="not(xpathInDocument2)">
<xsl:value-of select="$parameter_referenceDocument1.xpathInDocument1"/>
</xsl:if>
</elementName>
I know its ugly, but solves the problem. If anyone has a better solution, please let me know.

No, the BPEL standard requires the engine to throw a selectionFailure in this case. To avoid such situations, make sure you have properly initialized variables and/or validate variable against a schema. Also you may guard an assign activity with an if/switch activity to check for the presence of the element before accessing it. You may also consider writing an custom XPath function that returns a default value in case the demanded element does not exist in the variable. However, I'm not sure if the Oracle BPEL engine supports that.

You can create a scope around the assign activity and using an exception handler on the scope catch the selectionFailure, the item which will then carry on processing.
In the exception handler you could then assign a default value if required.
To clarify Vanto's statement, the Oracle BPEL engine does support custom XPath functions which would allow you to do that.

Related

XPath fails because Namespace colon in Title

I'm generating an XML report, using the JDF standard for PDFs going into a printing workflow.
There are 3 "DPart" sections, and I can use an xPath query to recognize them, but I want to grab the "Separation" attribute of each "cip4:Part". I can also get a query to find that, but it does not distinguish between the multiple "DPart"s.
<DPart End="0" ID="0003" ParentRef="0002" Start="0">
<DPM>
<cip4:Root>
<cip4:Intent cip4:ProductType="ProductPart"/>
<cip4:Production>
<cip4:Resource>
<cip4:Part Separation="K1"/>
<cip4:Color cip4:ActualColorName="Black" cip4:ColorType="Normal">
</cip4:Resource>
<cip4:Resource>
<cip4:Part Separation="S1"/>**
<cip4:Color cip4:ActualColorName="Dieline" cip4:ColorType="Normal">
</cip4:Resource>
<cip4:Resource>
<cip4:ColorantControl ColorantOrder="K1 S1" ColorantParams="K1 S1"/>
</cip4:Resource>
<cip4:Resource>
<eg:InkCoverage>
<eg:InkCov eg:Mm2="0.000000" eg:Pct="0.000000" eg:Separation="K1"/>
<eg:InkCov eg:Mm2="182.337538" eg:Pct="0.721209" eg:Separation="S1"/>
</eg:InkCoverage>
</cip4:Resource>
</cip4:Production>
</cip4:Root>
</DPM>
</DPart>
I want to do something like:
/DPM[2]/*[name ()='cip4:Part'], but it's not working.
I'm in a low-code pre-press environment (Esko Automation Engine), but the system gives me tools to parse an xPath, and throw some JavaScript at it.
There are at least three reasons your XPath selects nothing:
DPM is not an immediate child of the root node
There is only one DPM, so DPM[2] won't select anything
There is no child of a DPM whose name is cip4:Part.
You also say in the narrative that there are three DPart's, which implies that DPart is not actually the outermost element as it appears to be in your sample. This makes it difficult to provide the correct XPath. However, you might be able to make a start with
(//DPM)[2]//*[name()='cip4:Part']

Can't select XML attributes with Oxygen XQuery implementation; Oxygen XPath emits result

I learned that every Xpath expression is also a valid Xquery expression. I'm using Oxygen 16.1 with this sample XML:
<actors>
<actor filmcount="4" sex="m" id="15">Anderson, Jeff</actor>
<actor filmcount="9" sex="m" id="38">Bishop, Kevin</actor>
</actors>
My expression is:
//actor/#id
When I evaluate this expression in Oxygen with Xpath 3.0, I get exactly what I expect:
15
38
However, when I evaluate this expression with Xquery 3.0 (also 1.0), I get the message: "Your query returned an empty sequence.
Can anyone provide any insight as to why this is, and how I can write the equivalent Xquery statement to get what the Xpath statement did above?
Other XQuery implementations do support this query
If you want to validate that your query (as corrected per discussion in comments) does in fact work with other XQuery implementations when entered exactly as given in the question, you can run it as follows (tested in BaseX):
declare context item := document { <actors>
<actor filmcount="4" sex="m" id="15">Anderson, Jeff</actor>
<actor filmcount="9" sex="m" id="38">Bishop, Kevin</actor>
</actors> };
//actor/#id
Oxygen XQuery needs some extra help
Oxygen XML doesn't support serializing attributes, and consequently discards them from a result sequence when that sequence would otherwise be provided to the user.
Thus, you can work around this with a query such as the following:
//actor/#id/string(.)
data(//actor/#id)
Below applies to a historical version of the question.
Frankly, I would not expect //actors/#id to return anything against that data with any valid XPath or XQuery engine, ever.
The reason is that there's only one place you're recursing -- one // -- and that's looking for actors. The single / between the actors and the #id means that they need to be directly connected, but that's not the case in the data you give here -- there's an actor element between them.
Thus, you need to fix your query. There are numerous queries you could write that would find the data you wanted in this document -- knowing which one is appropriate would require more information than you've provided:
//actor/#id - Find actor elements anywhere, and take their id attribute values.
//actors/actor/#id - Find actors elements anywhere; look for actor elements directly under them, and take the id attribute of such actor elements.
//actors//#id - Find all id attributes in subtrees of actors elements.
//#id - Find id attributes anywhere in the document.
...etc.

Xpath Expression evaluation on attributes with any namespace prefix

Could you please help me on this xpath expression evaluation
I am working on fetching the proxy references. In the xml file the references will get stored as:
One way of XML file will have the reference as below:
con1:service ref="MyProject/ProxyServices/service1"
xsi:type="con2:PipelineRef" xmlns:ref="http://www.bea.com/wli/sb/reference"/
here in the xml file the name spaces are:
xmlns:con1="http://www.bea.com/wli/sb/stages/config"
xmlns:con2="http://www.bea.com/wli/sb/pipeline/config"
Another way of XML will have the reference as below.
con1:service ref="MyProject/ProxyServices/service2"
xsi:type="ref:ProxyRef" xmlns:ref="http://www.bea.com/wli/sb/reference"/
here in the xml file the name spaces are:
xmlns:con1="http://www.bea.com/wli/sb/stages/config"
xmlns:ref="http://www.bea.com/wli/sb/reference"
I have used this xpath expression, this is not fetching the reference service values, could you please help what is wrong in it.
"//service[#type= #*[local-name() ='ProxyRef' or #type=#*[local-name() ='PipelineRef']]/#ref"
when I used like this it is working but, name space prefix is keep on changes when there are multiple references in the xml file.
"//service[#type='ref:ProxyRef'or #type='con:PipelineRef' or #type='con1:PipelineRef' or #type='con2:PipelineRef' or #type='con3:PipelineRef' ...#type='con20:PipelineRef' ]/#ref";
Now here basically the type attribute PipelineRef is keep on changing the name space prefix from con to con(n). Now I am looking for something which supports some thing like #type='*:PipelineRef' or #type='con*:PipelineRef' or the best way to fetch the service element reference attribute value.
Thanks in advance.
Try using contains() like so :
//service[contains(#type,':ProxyRef') or contains(#type,':PipelineRef')]
Another alternative would be using ends-with() function which is more precise for this purpose compared to contains() function. However, ends-with() isn't available in xpath 1.0, so there is a chance that you need to implement it yourself (feasible, but the xpath result is less intuitive for me).

Can I get the information at which node or element or attribute the xpath failed while evaluating it against an xml

I have some xpath and I am evaluating against an XML.
//view/section/row
[(cell/data[#value='Other Roles']) and
(cell/data[contains(#value,'336')]) and
(cell/data[contains(#value,'0')]) and
(cell/data[contains(#value,'320')]) and
(cell/data[contains(#value,'16')]) and
(cell/data[contains(#value,'0')]) ]
While doing so, the xpath might not be available say row does not have the cell with data 336 , can I get that piece of information where it failed
Any code/utils that gives this information
In general, No.
Even if the result set is empty, it does not mean it fails. It is just an empty result set, which is a valid result. So as a matter of fact, your assumption is wrong, because the XPath did not fail.
If you want to check whether your XPath yiels an empty sequence, you can check using fn:empty(), e.g. empty(cell/data[contains(#value,'336')]).
Using XPath 2.0 you can also raise your own errors, using the fn:error() function. However, I do not see how you want to apply that in this specific example in a useful manner.
I've not seen any tools that automatically do this, but manually performing such sanity checks can be very useful:
First check that you're matching views:
//view
then sections:
//view/section
then rows:
//view/section/row
then specific rows:
//view/section/row[(cell/data[#value='Other Roles'])]
...until you get to a point where reality deviates from your expectations. You'll then know where an adjustment must be made.

How do I verify an xPath expression in Selenium IDE?

How would I test for the following expression in Selenium?
not(//select[#id='ddlCountry']/#class) or
not(contains(//select[#id='ddlCountry']/#class,'invalidValue'))
true if the class attribute doesnt exist, or if it does, the attribute doesn't contain invalidValue.
I've tried using the verifyElementPresent command, but it errors out, I assume because I'm returning a boolean rather than a node.
I'm happy with an alternative to this if theres no way to do the above using xPath.
In case your XPath engine API doesnt allow expressions returning atomic values (not nodes), then you still can
Use:
//select[#id='ddlCountry'][contains(#class,'invalidValue')]
and test if an element was selected or not.
true if the class attribute doesnt
exist, or if it does, the attribute
doesn't contain invalidValue.
not(//select[#id='ddlCountry']/#class[contains(.,'invalidValue')])

Resources