How to use XPath to find nodes in the XML attribute with ref? - xpath

I am trying to access the attribute/element nodes with ref in the below xsd
<xs:attributeGroup name="arcAttrs">
<xs:attribute ref="xlink:type" use="required" fixed="arc"/>
<xs:attribute ref="xlink:arcrole"/>
<xs:attribute ref="xlink:title"/>
<xs:attribute ref="xlink:show"/>
<xs:attribute ref="xlink:actuate"/>
<xs:attribute ref="xlink:from"/>
<xs:attribute ref="xlink:to">
<xs:annotation>
<xs:documentation>
from and to have default behavior when values are missing
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:group name="arcModel">
<xs:sequence>
<xs:element ref="xlink:title" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:group>
<xs:complexType name="arcType">
<xs:group ref="xlink:arcModel"/>
<xs:attributeGroup ref="xlink:arcAttrs"/>
</xs:complexType>
I try to access it by
<bindings node="xs:complexType[#name='arcType']">
<bindings node="xs:group/xs:element[#ref='xlink:title']">
<property name="arcModelTitle"/>
</bindings>
</bindings>
but it doesn't work…… what should I do about this?
What I want to do is : generate JAVA package from xsd by xjc. However,there’re some name conflict in the xsd, like the error below:
[ERROR] Property "Title" is already defined. Use <jaxb:property> to resolve this conflict.
line 197 of file:/D:/0Ubiloc/TEST/xlink.xsd
[ERROR] The following location is relevant to the above error
line 183 of file:/D:/0Ubiloc/TEST/xlink.xsd
so I want to redefined the name of the attribute or the element. But it failed to get the node(attribute/element) with ref, just like the code I stick out on the floor 1
Thanks in advance

Related

Where is the schema of `child-resources` specified?

I'm trying to find where the schema of the result of a child-resources query is specified in the xsd. It's clearly not a primitiveContent (specified in responsePrimitive) because that doesn't contain the named child-resources arrays.
I think this is in the CDT-responsePrimitive-v.xsd file. In Resourcewrapper you have "m2m:sg_regularResource":
<xs:complexType name="resourceWrapper">
<xs:sequence>
<xs:choice minOccurs="1" maxOccurs="1">
...
<xs:element ref="m2m:sg_regularResource" />
...
</xs:choice>
<xs:element name="URI" type="xs:anyURI" />
</xs:sequence>
</xs:complexType>
In any of the resources that is a "m2m:sg_regularResource" you can find a section like this that allows for "included" child resources:
...
<!-- Child Resources -->
<xs:choice minOccurs="0" maxOccurs="1">
<xs:element name="childResource" type="m2m:childResourceRef" minOccurs="1" maxOccurs="unbounded" />
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element ref="m2m:aResourceType" />
<xs:element ref="m2m:anotherResourceType" />
</xs:choice>
</xs:choice>
...

XSD for auto closing tag in complexType

I have this in my XML file:
<rooms>
<room id="1" beds="1" windows="0"/>
<room id="2" beds="2" windows="0"/>
</rooms>
And this in my XSD file:
<xs:complexType name="Rooms">
<xs:sequence>
<xs:element name="room" type="Room"/>
</xs:sequence>
<xs:attribute name="count" type="xs:integer"/>
</xs:complexType>
<xs:complexType name="Room">
<xs:attribute name="id" type="xs:integer"/>
<xs:attribute name="beds" type="xs:integer"/>
<xs:attribute name="windows" type="xs:integer"/>
</xs:complexType>
But I got this error : Element 'room': This element is not expected.
When I put <room id="1" beds="1" windows="0"></room> I don't have the error anymore and if I have only one room I don't have the error, so it's basically because of the auto closing tag.
How can I fix this?
Try specifying values for minOccurs and maxOccurs to your room element inside the sequence. I think the default expected number of occurrences is 1. Something like:
<xs:sequence>
<xs:element name="room" type="Room" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>

XSD key not in root element and complex keys

I searched for this, but can't find solution to my problem, so please don't trash this question.
We have a service with very complex XML configuration which is described by XSD. There are many rules that must be obeyed for things to run smoothly. XSD describes structure of configuration, but not the rules, which we must do now. After creating some global rules we have to do some more complex now and we encountered a problem. It seams like validator only uses key/keyref/unique from root element. I've created small XSD and XML file to illustrate that:
XSD:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://test.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns="http://test.org/XMLSchema.xsd"
xmlns:t="http://test.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Orders" type="t:OrdersList">
<xs:key name="OrderNo">
<xs:selector xpath="./t:Order" />
<xs:field xpath="#Number" />
</xs:key>
</xs:element>
<xs:complexType name="OrdersList">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Order" nillable="false" type="t:Order" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Order">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Lines" nillable="false" type="t:OrdersLinesList" />
</xs:sequence>
<xs:attribute name="Number" use="optional" type="xs:string" />
<xs:attribute name="ClientId" use="optional" type="xs:int" />
</xs:complexType>
<xs:complexType name="OrdersLinesList">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Line" nillable="false" type="t:OrderLine">
<!-- THE PROBLEM -->
<xs:key name="LineNoKey">
<xs:selector xpath="./t:Line" />
<xs:field xpath="#LineNumber" />
</xs:key>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="OrderLine">
<xs:attribute name="LineNumber" use="optional" type="xs:string" />
<xs:attribute name="ProductId" use="optional" type="xs:int" />
<xs:attribute name="Amount" use="optional" type="xs:decimal" />
</xs:complexType>
</xs:schema>
XML:
<?xml version="1.0" encoding="utf-8"?>
<Orders xmlns="http://test.org/XMLSchema.xsd">
<Order Number="0001/5/13" ClientId="123">
<Lines>
<Line LineNumber="1" ProductId="123" Amount="4" />
<Line LineNumber="2" ProductId="124" Amount="4" />
</Lines>
</Order>
<Order Number="0002/5/13" ClientId="123">
<Lines>
<Line LineNumber="1" ProductId="123" Amount="4" />
<!-- Duplicate number - it DOES validate as expected. -->
<Line LineNumber="1" ProductId="124" Amount="4" />
</Lines>
</Order>
<!-- Duplicate number - it doesn't validate as expected. -->
<Order Number="0002/5/13" ClientId="123">
<Lines>
<Line LineNumber="1" ProductId="123" Amount="4" />
<Line LineNumber="2" ProductId="124" Amount="4" />
</Lines>
</Order>
</Orders>
I have a few questions which I can't find any sensible answer:
How to solve the above. LineNumber must be unique, but only within Order/Lines.
Is it possible to allow keyref to contain non existing virtual value (our service uses some predefined... let say things. Custom ones are defined in XML to allow extending functionality, but in most of the cases, users will use predefined ones)
Is there any way to determine if list of elements within a tag (something like Lines above) has at least one tag with attribute set to certain value. Good example would be to describe it like a list of tables with unique names, that has list of columns with unique names and at least one of the columns is a primary key.
This is the corrected constraint for Lines/Line:
<xs:complexType name="Order">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Lines" nillable="false" type="t:OrdersLinesList">
<!-- THE PROBLEM SOLVED -->
<xs:key name="LineNoKey">
<xs:selector xpath="t:Line"/>
<xs:field xpath="#LineNumber"/>
</xs:key>
</xs:element>
</xs:sequence>
<xs:attribute name="Number" use="optional" type="xs:string"/>
<xs:attribute name="ClientId" use="optional" type="xs:int"/>
</xs:complexType>
If always helps if you can visualize your constraints, to understand the scope they act upon:
The correct diagram:
vs. the original one:
You can see that the selector rooted in the element Line is looking for yet another Line (./t:Line); and even if you fix the selector, it'll always match at most one attribute. The idea of a key is that the selector should match a set of nodes among which the field must be present and unique.
The above should take care of 1.
No.
Not based on an attribute. To stick with your parallel, for XSD 1.0 I would probably enforce an element called PrimaryKey, which should contain one or more references to names of the other columns; as if instead of using the PRIMARY KEY constraint clause in a column definition, I would enforce the use of the same at the table level.

Complex XPaths using EclipseLink MOXy and JAXB

I am currently using EclipseLink MOXy 2.4.1 and trying to update an element's value via XPaths.
The input used is :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<expenseReport>
<user>
<userName>Sanaulla</userName>
</user>
<items>
<item>
<itemName>Seagate External HDD</itemName>
<purchasedOn>August 24, 2010</purchasedOn>
<amount>6776.5</amount>
</item>
<item>
<itemName>External HDD</itemName>
<purchasedOn>August 24, 2010</purchasedOn>
<amount>677336.5</amount>
</item>
</items>
</expenseReport>
The XSD is
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="expenseReport" type="ExpenseT"/>
<xs:complexType name="ExpenseT">
<xs:sequence>
<xs:element name="user" type="UserT"/>
<xs:element name="items" type="ItemListT"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="UserT">
<xs:sequence>
<xs:element name="userName" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ItemListT">
<xs:sequence>
<xs:element name="item" type="ItemT" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ItemT">
<xs:sequence>
<xs:element name="itemName" type="xs:string"/>
<xs:element name="purchasedOn" type="xs:string"/>
<xs:element name="amount" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
And my Java code is :
JAXBContext context = JAXBContext.newInstance("sample.jaxb.xsd");
JAXBElement<ExpenseT> element = (JAXBElement<ExpenseT>)unmarshaller.unmarshal(new File("resources/sample_before.xml"));
ExpenseT expenseReport = element.getValue();
context.setValueByXPath(expenseReport, "items/item[1]/amount/text()", null, "100.11");
/** Marshalling code **/
I have my java classes created from the XSD using Moxy's tool "jaxb-compiler.cmd".
As you can see from the above code, I am trying to set the amount of 1st item to "100.11". But it doesn't set the value, nor does it throw any exception.
I tried setting the username above using XPath like this
context.setValueByXPath(expenseReport, "user/userName/text()", null, "ABC");
And, it does set/update the value properly.
Can you please advise on how can I set values for complex XPaths with Predicates? Something like this :
items/item[itemName='Seagate External HDD']/amount
We recently fixed a bug in our EclipseLink 2.4.2 and 2.5.0 streams related to setting values in which the XPath contains a postional indicator (ie "foo[1]/bar[2]/text()"). You can download a nightly build from the following link:
http://www.eclipse.org/eclipselink/downloads/nightly.php
You can use predicates in mappings with #XmlPath (see: http://blog.bdoughan.com/2011/03/map-to-element-based-on-attribute-value.html), but we currently don't supports this with our setValueByXPath call. Could you open an enhancement

case-insensitive key in xsd

I have an XSD embedded into an XML like this:
<Replacements>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Replacements">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="Replace" />
</xs:sequence>
</xs:complexType>
<xs:key name="ReplaceKey">
<xs:selector xpath="./Replace"/>
<xs:field xpath="#old"/>
</xs:key>
</xs:element>
<xs:element name="Replace">
<xs:complexType>
<xs:attribute name="old" type="AnythingButLowerCase" use="required" />
<xs:attribute name="new" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<xs:simpleType name="AnythingButLowerCase">
<xs:restriction base="xs:string">
<xs:pattern value="[^a-z]+"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
<Replace old="A1020____9" new="A1020"/>
<Replace old="a1020____9" new="A1020"/>
</Replacements>
I've used xs:key to define a unique-key on "old" attribute of Replace elements.
my problem is I want this key to be CASE-INSENSITIVE.
I've read so many documents indicating I can use xsd functions like upper-case or translate to solve this, but if I write something like
<xs:field xpath="upper-case(#old)"/>
VS2010 gives me a warning like this:
'upper-case(#old)' is an invalid XPath for selector or field.
What is it I'm doing wrong?
Thanks :)
The correct XPath function is "upper-case", not "upper case". Just add in the hyphen.
OK!
I got that!
Using functions in an xpath for a xs:field is not allowed.
The workaround for what I was seeking is to define a simpleType and put a restriction there not allowing lower-case letters.
Something like this:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Replacements>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Replacements">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="Replace" />
</xs:sequence>
</xs:complexType>
<xs:key name="ReplaceKey">
<xs:selector xpath="./Replace"/>
<xs:field xpath="#old"/>
</xs:key>
</xs:element>
<xs:element name="Replace">
<xs:complexType>
<xs:attribute name="old" type="AnythingButLowerCase" use="required" />
<xs:attribute name="new" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<xs:simpleType name="AnythingButLowerCase">
<xs:restriction base="xs:string">
<xs:pattern value="[^a-z]+"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
<Replace old="A1020____9" new="A1020"/>
<Replace old="a1020____9" new="A1020"/>
</Replacements>
Now this serves as what I want it to.

Resources