Validate that URI is not empty in RelaxNG - validation

I'm trying to validate that an element always has an href attribute in RelaxNG, and assumed you could do it with this:
<attribute name="href">
<data type="anyURI"/>
</attribute>
Only catch is, apparently anyURI considers empty strings to be valid, so href="" passes with flying colors. Is there any easy way to fix this?

You can use the minLength facet. For example:
<attribute name="href">
<data type="anyURI">
<param name="minLength">5</param>
</data>
</attribute>
See also http://www.w3.org/TR/xmlschema-2/#anyURI

Related

Can I get xpath count value in robot framework

Assume the following XML:
<data>
<node id="1" />
<node id="2" />
<node id="12" />
<node id="16" />
</data>
This xpath expression should be valid:
count(//node)
.. and should produce the number 4
I'm new to robot frameworks. Is it possible to use this xpath in robot framework?
for example something like:
${value}= Get something something source=${xml} xpath=count(//node)
The one below works but I would like the xpath to produce the end value, not a list.
#{nodelist}= Get Elements ${xml} xpath=node
Length Should Be ${nodelist} 4
Edit
I know that I can count the nodes in a list of nodes. However, I would like to get the absolute value (integer or string) using xpath. Now I need to write different code depending on if the xpath result is a node, list or attribute when the xpath could theoretically produce the final value.
You can use the Get Element Count Keyword it returns the number of elements matching the locator
You can do something as simple as this
${count} = Get Element Count name:div_name
Should Be True ${count} > 2
For more info on Keywords Have a look at this Keyword Page
When working with XML it is generally best to use the XML library. In the below example you'll find a solution for counting the elements using the XML library Get Element Count.
data.xml
<data>
<node id="1" />
<node id="2" />
<node id="12" />
<node id="16" />
</data>
Testcase.robot
*** Settings ***
Library XML
Library OperatingSystem
*** Test Cases ***
TC
${xml} Get File ./data.xml
${count} Get Element Count ${xml} xpath=node
Should Be Equal As Integers ${count} ${4}

How to print nested xml elements?

Sample xml:
<Root>
<Customers>
<Customer>
<CompanyName>Great Lakes Food Market</CompanyName>
<ContactName>Howard Snyder</ContactName>
<ContactTitle>Marketing Manager</ContactTitle>
<Phone>(503) 555-7555</Phone>
<FullAddress>
<Address>2732 Baker Blvd.</Address>
<City>Eugene</City>
<Region>OR</Region>
<PostalCode>97403</PostalCode>
<Country>USA</Country>
</FullAddress>
</Customer>
</Customers>
</Root>
In the above xml, when I use "Customer" as the root node and xpath query as "/Root/Customers/Customer", I'm unable to print the child nodes of "FullAddress" and when I use "FullAddress" as the root node and the xpath query as "/Root/Customers/Customer/FullAddress", unable to print all the fields.
Kindly help me with the solution to print all the xml elements including the nested in a single report.
The correct XPath query is
<queryString language="XPath">
<![CDATA[/Root/Customers/Customer]]>
</queryString>
This include both of your nodes, to access the value is FullAddress node you should use XPath also in fieldDescription when you define your field, hence Address is accessed through FullAddress/Address
Example
If the field declaration of CompanyName is
<field name="CompanyName" class="java.lang.String">
<fieldDescription><![CDATA[CompanyName]]></fieldDescription>
</field>
the field declaration of for example the City is
<field name="City" class="java.lang.String">
<fieldDescription><![CDATA[FullAddress/City]]></fieldDescription>
</field>

Appending multiple strings in Oracle SOA Suit in a BPEL process

I'm new to the Oracle SOA Suite and I have created a basic BPEL process that allows you to create a "User" with some basic values.
XSD:
//INPUT
<element name="User">
<complexType>
<sequence>
<element name="First_Name" type="string"/>
<element name="Last_Name" type="string"/>
<element name="Age" type="string"/>
<element name="DOB" type="string"/>
</sequence>
</complexType>
</element>
// String to output
<element name="processResponse">
<complexType>
<sequence>
<element name="Output" type="string"/>
</sequence>
</complexType>
</element>
So using this XSD I want to be able to create a user, and append all the values together and create a response/reply with my synchronous BPEL process.
I've tried simply adding all the values together using the '+' operation but doesn't work as it tries to cast it it a integer, so it seems and the value comes out as "Jon NaN".
<copy>
<from>concat("Hello! ", $inputVariable.payload/ns1:Last_Namel)</from>
<to>$outputVariable.payload</to>
</copy>
I've also tried to use multiple concat's but it get's real ugly real quick, and something i would like to avoid is messy code.
So as a summary i want to be able to take all the input values (First Name, Last Name, Age, DOB) and convert them into a nice string with some padding and extra hard coded strings to show a nice message at the end.
Give all the values which you require to be concatenated comma separated in the concat() function:
<from>concat('Hello! ', $inputVariable.payload/ns1:Last_Name,' ',$inputVariable.payload/ns1:First_Name,' ',$inputVariable.payload/ns1:Age,' ',$inputVariable.payload/ns1:DOB)</from>
<to>$outputVariable.payload/Output</to>

xpath expression wild-cards

I have a requirement to specify wild card in the following xpath
Field[#name="/Root/Table[i]/FirstName"]
Basically the "i" would be a variable which can have either a GUID or a running number. I would like to pick up all elements that basically have the attribute pattern
"/Root/Table[*]/FirstName"
i.e. starting with "/Root/Table[" and ending with "]/FirstName". Any ideas as to how this can be done ?
Here is a sample payload:
<Package>
<Input>
<Data id="36e9f0fe3f8d4508ac20710e07cfddd4">
<Input>
<Field name="/Root/Table[1]/FirstName">Thomas</Field>
</Input>
</Data>
</Input>
</Package>
You should be able to do this using starts-with() and a makeshift ends-with() (since XPath 1.0 doesn't actually have an ends-with() function):
//*[starts-with(#name, '/Root/Table[') and
substring(#name, string-length(#name) - 11 + 1) = ']/FirstName']
Here, 11 is the length of ]/FirstName.

Double node on Xpath for different values

How to write a Xpath for two attributes? e.g. i need to get a value of discount > 20% and also the same discount is greater than amount 200(without any link to base value)
You can combine constraints in predicates. E.g.:
from lxml import etree
doc = etree.XML("""<xml>
<items>
<item discount_perc="25" discount_value="250">Something</item>
</items>
</xml>
""")
doc.xpath('items/item[#discount_perc > 20 and #discount_value > 200]')
Will try to answer by a simple example. Imagine you have the following xml:
<?xml version="1.0"?>
<data>
<node value="10" weight="1">foo</node>
<node value="10" weight="2">bar</node>
</data>
Then use this query to select the first <node>'s text:
//node[#value="10" and #weight="1"]/text()
and this for the second:
//node[#value="10" and #weight="2"]/text()
Hope this helps.

Resources