I am having problems using a schema in either DTD or XSD format to validate XML returned to JMeter.
The error code I am getting is this.
Assertion error: true
Assertion failure: false
Assertion failure message: error: line=1 col=71 schema_reference.4: Failed to read schema document 'schema.dtd', because
1) could not find the document;
2) the document could not be read;
3) the root element of the document is not <xsd:schema>.
I have made sure the schema is in this same location as the Jmeter test and is not read only etc.
Sample DTD
<!ELEMENT userId (#PCDATA)>
<!ELEMENT recordId (#PCDATA)>
<!ELEMENT operationDateTime (#PCDATA)>
<!ELEMENT operationCode (#PCDATA)>
<!ELEMENT oldVal (#PCDATA)>
<!ELEMENT newVal (#PCDATA)>
<!ELEMENT listOfAuditItems ((auditItem))>
<!ELEMENT fieldName (#PCDATA)>
<!ELEMENT buscomp (#PCDATA)>
<!ELEMENT auditItem ((recordId, userId, operationCode, buscomp, operationDateTime, fieldName, oldVal, newVal))>
<!ELEMENT ariResponse ((listOfAuditItems))>
I checked the validity of the DTD file here and it passed!
Sample XML
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<ariResponse>
<listOfAuditItems>
<auditItem>
<recordId>2-1DFSGT</recordId>
<userId>1-1SJKJS</userId>
<operationCode>Modify</operationCode>
<buscomp>Service Request</buscomp>
<operationDateTime>2010-05-12T15:23:53.000+05:30</operationDateTime>
<fieldName />
<oldVal />
<newVal />
<auditLog>2*C311*EVT_STAT_CD16*TODO_PLAN_END_DT11*OWNER_LOGIN2*N34*Open19*2011-01-06
16:28:567*RITESHP2*O30*0*0*
</auditLog>
</auditItem>
</listOfAuditItems>
<returncode>0</returncode>
<errormessage />
</ariResponse>
Thanks!
Summary: in the end I've used http://path.to.schema/myschema.xsd as the File Name parameter in the Assertion.
Explanation: following Alies Belik's advice, I've found that the code for setting up the schema looks something like this:
DocumentBuilderFactory parserFactory = DocumentBuilderFactory.newInstance();
...
parserFactory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", xsdFileName);
where xsdFileName is a string (the attribute string is actually a constant, I inlined it for readability).
According to e.g. this page, the attribute, when in the form a String, is interpreted as an URI - which includes HTTP URLs. Since I already have the schema accessible through HTTP, I've opted for this solution.
Related
I have this test XML file:
<?xml version="1.0"?>
<!DOCTYPE main [
<!ELEMENT main (object+)>
<!ELEMENT object (description, year, manufacturer)>
<!ATTLIST object name CDATA #REQUIRED>
<!ATTLIST object works (yes|no) "yes">
<!ELEMENT description (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT manufacturer (#PCDATA)>
]>
<main>
<object name="My object">
<description>This is a simple object</description>
<year>2022</year>
<manufacturer>Myself</manufacturer>
</object>
</main>
and this piece of Python code:
import xml.etree.ElementTree
try:
xml_data = xml.etree.ElementTree.iterparse("test.xml", events=("start", "end"))
for event, xml_tag in xml_data:
if event == "end" and xml_tag.tag == "object":
object_name = xml_tag.get("name")
object_description = xml_tag.find("description").text
works = xml_tag.get("works")
print("works value: " + str(works))
xml_tag.clear()
print("Done!")
except (NameError, xml.etree.ElementTree.ParseError):
print("XML error!")
The output of the code is this:
works value: yes
Done!
Reading library documentation I can't find any tip on ATTLIST value, works attribute is not present for object element so I expect that the code return this output:
works value: None
Done!
If I remove this line from XML
<!ATTLIST object works (yes|no) "yes">
the output is what I expect. I tried to use
works = xml_tag.get("works", default=None)
without success. Is there a way to override ATTLIST default value? XML is out of my control and it can change over time
I use an XML Schema Definition and JAXB to generate Java classes with proper #XmlElement or #XmlRootElement annotations.
Since the schema has some deep nesting in it (not my choice), I'd rather use jxpath to access deeply buried classes using an XPath (rather than cumbersome daisy-chain of .getThat() and that != null).
The problem is that some of the XML element names contain dashes, e.g. foo-bar. When I try to access elements using org.apache.jxpath, I need to rewrite my XPath so that such names are camel-cased instead (fooBar) like the name of the actual Java objects. Is there any way to tell jxpath to find the elements using the XPath corresponding to the XML element names (instead of the camel-cased Bean names)?
I think it is related to this question, however in my case I don't actually case what kind of tricks and decorations are used on the auto-generated classes, as long as xjc can do it.
Here is a simple example to illustrate the issue.
First, a small XSD file:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="record">
<xs:complexType>
<xs:sequence>
<xs:element name="foo-bar" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Compile it...
xjc -p org.pd.jx example.xsd
Here is the xjc-generated Record.java class (minus comments):
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {"fooBar"})
#XmlRootElement(name = "record")
public class Record {
#XmlElement(name = "foo-bar", required = true)
protected String fooBar;
public String getFooBar() {return fooBar;}
public void setFooBar(String value) {this.fooBar = value;}
}
Then, trying to access the data via jxpath (in practice I have to deal with lots of deeply nested classes), one can see below that the correct XPath ("foo-bar") doesn't work, but a camel-cased version does.
Record record = new Record();
record.setFooBar("hello world");
JXPathContext context = JXPathContext.newContext(record);
context.setLenient(true);
String a = (String)context.getValue("foo-bar", String.class); // is null
String b = (String)context.getValue("fooBar", String.class); // "hello world"
I believe JXPath operates on an objects properties and not the XML elements they correspond to. I do not believe that JXPath parses any of the JAXB metadata so it wouldn't know the XML nodea you have mapped. What you are seeing appears to be the expected behaviour.
for example i have this xml:
<xml>
<a>1</a>
<b>2</b>
</xml>
and this class:
#XmlRootElement(name = "xml")
public class xml{
int aPlusb;
....
}
i know how to create an XmlAdapter but i would like it to set the filed aPlusb to be the plus between the value of element a and the value of filed b.
is there a way to do this in JAXB without making an XmlTransient field and calculate it separately?
I have created a sample XML. And trying to Read by using LINQ
here is the code:
XElement root = XElement.Load("C:\\............\\TestData.xml");
IEnumerable<Xelement> address = from tt in root.Elements("Test")
select tt;
I am getting compile time error at select statement :
Cannot implicitly convert type
'System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>'
to 'System.Collections.Generic.IEnumerable<EvalTest.Xelement>'.
An explicit conversion exists (are you missing a cast?)
XML:
<?xml version="1.0" encoding="utf-8" ?>
<TestData>
<Test Method="1">
<ID>1</ID>
<Submitter> Ritvij</Submitter>
<Date>11/5/2013 2:51:57 PM </Date>
</Test>
<Test Method="2">
<ID>1</ID>
<Submitter> Ritvij</Submitter>
<Date>11/5/2013 2:51:57 PM </Date>
</Test>
</TestData>
root.Elements returns an IEnumerable<XElement> (with a capital "E"), but you're trying to assign it to IEnumerable<Xelement> (lower case "e").
Either modify your code to use XElement or use var:
IEnumerable<XElement> address = from tt in root.Elements("Test") select tt;
var address = from tt in root.Elements("Test") select tt;
If I have the following XML:
<variables>
<variable name="age">92</variable>
<variable name="school">Fairview</variable>
<variable name="birthdate">11/13/2012</variable>
</variables>
Is there a way to create a schema where, based on the name attribute value, it then defines the node value (as decimal, string, date)? If so, how?
Update: This is for code in C# so I need to get this schema info using the >NET runtime.
thanks - dave
Here's a schema for your example in Relax NG
datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes"
element variable {
((
attribute name {'age'},
xsd:int) |
(
attribute name {'school'},
text) |
(
attribute name {'birthdate'},
xsd:date))
}