Castable don't work in XPATH in ORBEON 4.1 - xpath

. castable as xs:date doesn't work since we updated from ORBEON 3.9 to ORBEON 4.1. in the xforms:output tag (in both ref and value attributes).
The associated field is defined using an xsd file as xs:date, field itself has value '' (empty string).
The exception is:
org.orbeon.oxf.common.ValidationException: line 1136 of file:///D:/oracle/wls10.3.3/domains/gacr/ (evaluating XPath expression: expression='datumUkonceni castable as xs:date'): null file:///D:/oracle/wls10.3.3/domains/gacr/, line 1136, column -1: null
at org.orbeon.oxf.common.ValidationException.wrapException(ValidationException.java:126)
at org.orbeon.oxf.util.XPath$.handleXPathException(XPath.scala:170)
at org.orbeon.oxf.util.XPathCache$.withEvaluation(XPathCache.scala:516)
at org.orbeon.oxf.util.XPathCache$.evaluateAsString(XPathCache.scala:312)
at org.orbeon.oxf.xforms.control.ControlXPathSupport$class.evaluateAsString(ControlXPathSupport.scala:86)
at org.orbeon.oxf.xforms.control.XFormsControl.evaluateAsString(XFormsControl.scala:47)
at org.orbeon.oxf.xforms.control.controls.XFormsOutputControl.evaluateValue(XFormsOutputControl.scala:75)
at org.orbeon.oxf.xforms.control.XFormsValueControl$class.evaluateImpl(XFormsValueControl.scala:80)
at org.orbeon.oxf.xforms.control.controls.XFormsOutputControl.evaluateImpl(XFormsOutputControl.scala:58)
at org.orbeon.oxf.xforms.control.XFormsControl.evaluate(XFormsControl.scala:204)
at org.orbeon.oxf.xforms.control.ControlBindingSupport$class.setBindingContext(ControlBindingSupport.scala:102)
at org.orbeon.oxf.xforms.control.XFormsControl.setBindingContext(XFormsControl.scala:47)
at org.orbeon.oxf.xforms.control.ControlBindingSupport$class.evaluateBindingAndValues(ControlBindingSupport.scala:59)
at org.orbeon.oxf.xforms.control.XFormsControl.evaluateBindingAndValues(XFormsControl.scala:47)
.... stack continued
When I use this construction in properties-local.xml <property as="xs:string" name="oxf.xforms.format.output.date" value="if (. castable as xs:date)
then format-date(xs:date(.), '[D01].[M01].[Y0001]', xxforms:lang(), (), ()) else ."/>, then castable is processed as expected ...

With 4.0, use the xxf prefix, instead of xxforms, in your properties-local.xml and this should solve your problem.
In general, XML files in 4.0 have been changed to use shorter prefixes, like xxf instead of xxforms, xf instead of xforms, and xh instead of xhtml. In most cases, this change is backward compatible, as you do the prefix to namespace mapping in your own file, and thus are free to use whatever prefix you like, but there are exceptions.

The ref and value attributes of xforms:output tag in ORBEON 3.9 are almost same and xpath expressions in the ref atribute are executed. In the ORBEON 4.1 ref atribute must be reference to element - xpath expression castable as throws exception ..

Related

Specifying null with nifi expression language

I'm trying to replace an empty field with nulls in an UpdateRecord processor.
/title ${field.value:replaceEmpty(null)}
This fails because "null" is not a valid keyword. How does one specify null in the nifi expression language?
You can use the literal() function to return a String value that is the exact input to the function, and you can nest that inside your replaceEmpty method. Try using the expression ${field.value:replaceEmpty(${literal('null')})}.
If you are doing this in the UpdateRecord processor, you want to use Apache NiFi RecordPath syntax, not Expression Language. I believe the CSVReader and others parse even a field value containing only spaces to empty, so a regular expression like replaceRegex( /title, '^(?![\s\S])$', 'null' ) doesn't work.
My suggestion would be to file a Jira requesting this capability. In the mean time, do not use UpdateRecord for this, but rather ReplaceText with a regular expression like ,\s?, for an empty CSV value and replace it with null.
There is a trick using RecordPath, if the field value is blank you can do this to get a null value.
/fieldName[not(isBlank(/fieldName))]
It is giving answer as
{
"fieldname" : "null"
}
here null is a string not a null value.

How to get element by attribute name which ends with defined word

In my XML I have elements
<driverConfig name="ADriver">
...
</driverConfig>
<driverConfig name="BDriver">
...
</driverConfig>
Is there a way how to select all value of sub-element. Problem is I can modify just first name in this expression which I already tried but with no success:
//driverConfig[#name="*Driver"]/fd:properties/fd:property[#name="path"]
With XPath 2.0 you can do //driverConfig[ends-with(#name, 'Driver')]/fd:properties/fd:property[#name="path"] respectively //driverConfig[matches(#name, 'Driver$')]/fd:properties/fd:property[#name="path"].
With XPath 1.0 you can use //driverConfig[substring(#name, string-length(#name) - 5) = 'Driver']/fd:properties/fd:property[#name="path"].

Using String function in xpath returns value and a new line

I am using the following format for my xpath expression in VB.Net workflow:
String(xpath)
which returns me the expected string value, but also a new line charac after the value which is breaking my logic.
How do I get rid of that new line?
Any pointers?
More Info as requested:
The normalize-space is still returning the new line.
The xml is too big, so pasting the snippet under its immediate parent here:
<Characteristic_Value_Population_Rule_SpecChar_Value_Population_Rule ID="f0baf095-5e84-4146-9c72-7691205df16b" xsi:type="SpecChar_Value_Population_Rule" Pattern="T_RelatedEntityRule">
<Entity_T_RelatedEntityGroup_AND ID="a9adc94f-615b-477b-8841-94887429a83e" xsi:type="T_RelatedEntityGroup_AND" Pattern="TRelated_EntityGroup">
<Entities_TRule_Value_EntityRef ID="f521569f-41a3-42ad-9974-3aea9557460b" xsi:type="TRule_Value_EntityRef" Pattern="TRule_Complex_Value">
<Name>Modem ADSL/VDSL/TV/PSTN b-box 3 0</Name>
<Entity>000006,000069,000078</Entity>
</Entities_TRule_Value_EntityRef>
<Entities_TRule_Value_EntityRef ID="9025dfc0-bd7d-4252-8dad-f95a818b8688" xsi:type="TRule_Value_EntityRef" Pattern="TRule_Complex_Value">
<Name>Modem ADSL/VDSL2/TV/Italk/off b-box 2 039</Name>
<Entity>000006,000069,000077</Entity>
</Entities_TRule_Value_EntityRef>
<Name>Acquisition Type is Rent in the context of Belgacom Internet</Name>
</Entity_T_RelatedEntityGroup_AND>
<Name>Acquisition Type is Rent in the context of Belgacom Internet</Name>
<Characteristic ID="ae3f9304-31a7-4c0b-8723-c553b136410e" Pattern="TSpecChar" OrigType="SpecCharItem">
<Specification_Characteristic ID="c5dec18e-806c-46d1-8294-e83117650b5b" Pattern="TSpecCharValue" OrigType="SpecCharValueItem">
<Value>Rent</Value>
<IsUserDefinedValue>false</IsUserDefinedValue>
</Specification_Characteristic>
<Name>Acquisition Type</Name>
</Characteristic>
</Characteristic_Value_Population_Rule_SpecChar_Value_Population_Rule>
</Package>
I am trying to get the value c5dec18e-806c-46d1-8294-e83117650b5b which the xpath expression does return but with the new line.
i am now using the xpath:
string(normalize-space(//Package/Characteristic_Value_Population_Rule_SpecChar_Value_Population_Rule/Characteristic/Specification_Characteristic/#ID))
Try String(normalize-space(xpath)). If that does not help then show us more context.

How to check IDREFS count is bigger than 1 in xPath

Before this is marked as a duplicate, I need the xpath expression and not the xquery expression. So this didn't help me: How to check IDREFS length in xPath
Also, I tried using id function as suggested here: xpath: contains() for a group of answers
but this only returns empty results for me.
I'm using the xml plugin for Notpad++, if that matters.
I have the next DTD definition
<!ELEMENT testNode EMPTY>
<!ATTLIST testNode
listOfNodes IDREFS #REQUIRED
bestNode IDREF #REQUIRED
>
when I get /testNode/#listOfNodes I have to check if there are more than one ref in listOfNodes. How can I do that ?
Thanks!
One possibility with xpaht-1.0 is:
Check how many separators (space) are in the attribute. This could be done by length of original string minus length of string without spaces.
string-length( testNode/#listOfNodes) - string-length( translate(/testNode/#listOfNodes,' ',''))
Therefore you test would be:
string-length( testNode/#listOfNodes) - string-length( translate(/testNode/#listOfNodes,' ','')) +1 > 1
To find occurrences of the attribute with only a single token, I'd use //testNode/#listOfNodes[not(contains(.,' ')] -- if I were condemned to work in an environment without validation, that would change to //testNode/#listOfNodes[not(contains(normalize-space(.),' ')]. To find occurrences with multiple IDREF tokens, remove the not().

How to get node value using variable node name?

I have an XML document like:
<data>
<item type="apple">
<misc>something</misc>
<appleValue>23</appleValue>
<misc2>something else</misc2>
</item>
<item type="banana">
<bananaValue>47</bananaValue>
<random>something</random>
</item>
</data>
I can get the items with doc("data.xml")/data/item but I need to get the text from the elements that end with Value. So I'd like to get "23" and "47", but I don't necessarily know the element names, meaning all I really know is there are elements that end in Value, I don't know if it's appleValue, bananaValue, etc. except that I could look at the type attribute and buildup a string.
let $type := (doc("data.xml")/data/item)[1]/#type
doc("data.xml")/data/item/$typeValue
...That last line is what I'm trying to get at, clearly that's not correct but I need to find elements whose name is known based on a variable (stored in a variable such as $type) and "Value".
Any ideas? I realize this variable element naming is strange/odd/bad...but that's the way it is and I have to deal with it.
I got it thanks to this post: Can XPath match on parts of an element's name?
doc("data.xml")/data/item/*[ends-with(name(), "Value")]
I would avoid using the name() function in favor of either node-name() or local-name(). The reason for this is that name() can give you different answers depending on what (and whether) namespace prefixes are used in the source. For example, the following three elements have the same exact name (QName):
<appleValue xmlns="http://example.com"/>
<x:appleValue xmlns:x="http://example.com"/>
<y:appleValue xmlns:y="http://example.com"/>
However, the name() function will give you a different answer for each one (appleValue, x:appleValue, and y:appleValue, respectively). So you're better off either ignoring the namespace by using local-name() (which returns the string appleValue for all three of the above cases) or explicitly specifying the namespace (even if it's empty, as Oliver showed), using node-name() (which returns a proper QName value, rather than a string). In this case, since you're not using namespaces (and since even if you added one later, the code will still work), I'd be slightly in favor of using local-name() as follows:
doc("data.xml")/data/item/*['Value' eq substring-after(local-name(),../#type)]
For elaboration on reasons to avoid the name() function (and exceptions), see "Perils of the name function".
You can access the name of the node using name(). XPath 1.0 does not have an "ends-with" function, but by using substring() and string-length() - 1 you can get there.
//item/*[ substring( name(), string-length(name() ) - 4 ) = 'Value']
A more precise way to implement this would be
for $item in doc("data.xml")/data/item
let $value-name := fn:QName('', concat($item/#type, 'Value'))
return $item/*[node-name() = $value-name]

Resources