XInclude support in Java 6 - xinclude

I've seen this example posted several times:
public class XIncludeTest {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setXIncludeAware(true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
System.out.println("isXIncludeAware " + docBuilder.isXIncludeAware());
Document doc = docBuilder.parse(args[0]);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//initialize StreamResult with File object to save to file
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
String xmlString = result.getWriter().toString();
System.out.println(xmlString);
}
}
I pass this simple xml file in:
a.xml
<?xml version="1.0" encoding="UTF-8"?>
<a xmlns:xi="http://www.w3.org/2003/XInclude">
<xi:include href="b.xml" xpointer="element(/b/c)"/>
<xi:include href="b.xml" xpointer="element(/b/d)"/>
</a>
b.xml
<?xml version="1.0" encoding="UTF-8"?>
<b>
<c>1</c>
<d>2</d>
</b>
And all I get back out is the contents of a.xml, as above - no part of b.xml was included. I've tried endless variations on the xpointer syntax to no avail. I have, however, been able to get things to work in perl via XML::LibXML but I need this to work in Java.
What am I not getting?
OK, now I've updated my xml file to something that works:
a.xml
<?xml version="1.0" encoding="UTF-8"?>
<a xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="b.xml" xpointer="element(/1/1)"/>
<xi:include href="b.xml" xpointer="element(/1/2)"/>
</a>
I'd rather not use offsets into the document - names are much better (like in the first version of a.xml). I'm trying to understand XPointer Framework and have been using XPath and XPointer/XPointer Syntax as a reference as well - it seems I should be able to use a "shorthand" pointer but only if the NCName matches some ID-type attribute. Problem is that I don't have a DTD or schema that defines an "ID-type attribute". Given that the Java parser doesn't support the xpointer schema, is my only option to use indexes?

The namespace for the xi prefix should be "http://www.w3.org/2001/XInclude" (note 2001 not 2003). See http://www.w3.org/TR/xinclude/ for more details.
That gets you to what seems to be the next problem: the syntax of your element scheme xpointer is incorrect. See http://www.w3.org/TR/xptr-element/ for more information.

Related

BizTalk 2010 WCF Remove processing instruction

I need to do download an XML file from a public website (http://www.tcmb.gov.tr/kurlar/201707/10072017.xml) to get exchange rates.
But I have a problem since the XML contains an xml-stylesheet processing instruction.
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="isokur.xsl"?>
<Tarih_Date Tarih="07.07.2017" Date="07/07/2017" Bulten_No="2017/131" >
I use a WCF-Custom port with webHttpBindng and BizTalk REST starter kit from bLogical. Everything works fine, but when I try to parse the incoming xml, I get an error on that processing instruction.
System.Xml.XmlException: Processing instructions (other than the XML declaration) and DTDs are not supported. Line 2, position 2.
I'm not sure what the best way would be to fix this. I tried to follow this guide WCF Errors on XML Deserialization but it still fails when I try to access the message content using the CreateBufferedCopy method.
using (var readStream = new System.IO.MemoryStream())
{
using (var buffer = reply.CreateBufferedCopy(int.MaxValue))
{
buffer.WriteMessage(readStream);
}
readStream.Position = 0;
xdoc.Load(readStream);
}
Does anybody know how I can access the content of my message without actually parsing the XML? I'm just trying to find a way to either remove that line or make the parser ignore it.
I found the solution myself in the end. Instead of a message inspector, I created a Message Encoder based on the CustomTextMessageEncoder that you can find online.
In the ReadMessage method I just added a little bit of code
public override Message ReadMessage(System.IO.Stream stream, int maxSizeOfHeaders, string contentType)
{
XmlReaderSettings xsettings = new XmlReaderSettings();
xsettings.IgnoreProcessingInstructions = true;
XmlReader reader = XmlReader.Create(stream,xsettings);
return Message.CreateMessage(reader, maxSizeOfHeaders, this.MessageVersion);
}

Saxon .Net read xml from stream

all examples show how to read an xml from an local file. But how do I read a xml from a url or a stream and process it further?
Example: http://www.oreillynet.com/xml/blog/2006/03/hello_saxon_on_net_an_aspnet_i.html
thanks in advance
Look for XsltExamples.cs in the saxon-resources download available on both Sourceforge and www.saxonica.com. The very first example seems to do what you are asking for.
public static void ExampleSimple1(String sourceUri, String xsltUri) {
// Create a Processor instance.
Processor processor = new Processor();
// Load the source document
XdmNode input = processor.NewDocumentBuilder().Build(new Uri(sourceUri));
// Create a transformer for the stylesheet.
XsltTransformer transformer = processor.NewXsltCompiler().Compile(new Uri(xsltUri)).Load();
// Set the root node of the source document to be the initial context node
transformer.InitialContextNode = input;
// Create a serializer
Serializer serializer = new Serializer();
serializer.SetOutputWriter(Console.Out);
// Transform the source XML to System.out.
transformer.Run(serializer);
}
Are you using an XmlDocument object for reading the XML? If so, you'll want XMLDocument.Load() method, which can take a file path or URL, TextReader or Stream as input.
Likewise, XDocument.Load()(msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.load(v=vs.110).aspx) has a similar set of overloads.

How to get all element names with JDOM 2 via XPath in Java 7?

I have a XML file like the following.
<?xml version="1.0" encoding="UTF-8"?>
<Site>
<Name>MySite</Name>
<Groups>
<Default></Default>
<GroupA></GroupA>
</Groups>
</Site>
I want to get all names of Groups' children elements (in this example 'Default' and 'GroupA') as a list of strings. I was trying the following.
public List<String> getGroupNames() {
List<String> names = new ArrayList<String>();
XPathExpression<Text> xpath = XPathFactory.instance().compile(
"/Site/Groups/*/name()", Filters.text());
List<Text> elements = xpath.evaluate(document);
if (elements.size() > 0) {
for (Text text : elements) {
names.add(text.getText());
}
return names;
}
return null;
}
This fails hard with the following exception.
class org.jaxen.saxpath.XPathSyntaxException: /Site/Groups/*/name(): 20: Expected node-type
What is the proper syntax for that? I do not understand the exception.
It seems the XPathFactory instance you use only supports XPath 1.
You need to load a library supporting XPath 2, before being able using xpath 2. E.g: with SAXON:
import net.sf.saxon.om.NamespaceConstant;
String objectModel = NamespaceConstant.OBJECT_MODEL_SAXON;
System.setProperty("javax.xml.xpath.XPathFactory:"+objectModel, "net.sf.saxon.xpath.XPathFactoryImpl");

Manually deserialize WebRequest XML

SO I have an ASMX web service that returns a array of Search Result objects. When I call the WebMethod via the browser, the following XML is generated...
<?xml version="1.0" encoding="utf-8"?><ArrayOfSearchResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/"><SearchResult>
<Name>Rock Salt Steak House</Name>
<BusinessType>Steakhouses</BusinessType>
<Rating>mStar30</Rating>
<Address>1232 Westlake Ave N</Address>
<City>Seattle</City>
<State>WA</State>
<Phone>(206) 284-1047</Phone>
<Zip>98109</Zip></SearchResult><SearchResult>
<Name>Laredos Grill</Name>
<BusinessType>Tex-Mex Bars</BusinessType>
<Rating>mStar35</Rating>
<Address>555 Aloha St Ste 100</Address>
<City>Seattle</City>
<State>WA</State>
<Phone>(206) 218-1040</Phone>
<Zip>98109</Zip></SearchResult>.......
This XML gets saved in a file to be de-serialized later. The problem is I can't seem to get it serialized again. Here's the code I use....
XmlSerializer serializer = new XmlSerializer(typeof(List<Service.SearchResult>));
using (StringReader stringReader = new StringReader(strXMLContent)) // can throw ArgumentNullException
{
using (XmlReader xmlReader = XmlReader.Create(stringReader))
{
//xmlReader.Read();
return ((List<Service.SearchResult>)serializer.Deserialize(xmlReader)).ToArray(); // can throw SerializationException
}
}
The error I get is complaining about "there is an error in xml document (2,2)" and the inner exception is (InnerException = {"ArrayOfSearchResult xmlns='http://tempuri.org/' was not expected."})
Of course when calling this WebMethod in code the collection comes down easily. It isn't until I try to manually deserialize later that it's get's mad.
Any ideas would be greatly appreciated...
Thanks!
First, why are you calling it via WebRequest? Why not just use "Add Service Reference" and use the proxy class?
Secondly, when you're calling it in the browser, you're not using SOAP. Note the lack of SOAP Envelope in the response.

How to serialize java.sql.Date as Long, when using web services?

I have a simple web service method that returns a simple java class as return value.
#WebMethod()
public SimpleClass myMethod();
#XmlRootElement()
public class SimpleClass {
#XmlElement(name="myDate")
#XmlJavaTypeAdapter(value=MyDateAdapter.class)
public java.sql.Date myDate = new java.sql.Date(new java.util.Date().getTime());
}
I want that java.sql.Date will transmitted as Long value in the XML (because the client is J2ME that cannot handle complex things).
For this puprpose I took the solution that was mentioned in many places before, and worked great on Glassfish v2.
First, I declare the following adapter:
public class MyDateAdapter extends XmlAdapter<Long, java.sql.Date> {
public java.sql.Date unmarshal(Long v) throws Exception {
return new java.sql.Date(v);
}
public Long marshal(java.sql.Date v) throws Exception {
return v.getTime();
}
}
Then, I declare its usage in package-info file like this:
#XmlJavaTypeAdapters({
#XmlJavaTypeAdapter(value=MyDateAdapter.class,type=java.sql.Date.class)
})
package mingler.tracker.ejb.client;
The problem happens on GlassFish 3. The date is transmitted as "xs:dateTime" value, instead of Long, although I defined the adapter properly.
This is the response I get from GlassFish 3 server, when I call my web service:
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:myMethodResponse xmlns:ns2="http://nevermind.com">
<return>
<myDate xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:dateTime">2010-12-09T12:44:06.875+02:00</myDate>
</return>
</ns2:myMethodResponse>
</S:Body>
</S:Envelope>
I also checked with the debugger -- the functions in the adapter are never called.
On the other hand, the adapater is not useless, because if I try to remove it I get JAXB exception,
telling me that java.sql.Date cannot be handled because it doesn't have no-arg constructor.
Any ideas?
20/12/2010 -
I added links to a project jar with sources and the results for glassfish2 and glassfish3:
jar file ,glassfish3 result , glassfish2 result
I have posted a bug for this issue, it should be solved on version 3.1 (link)
You have the #XmlJavaTypeAdapter declared at both the property level and the package level. Have you tried only declaring it in one spot?
Either:
#XmlJavaTypeAdapter(value=MyDateAdapter.class)
public java.sql.Date myDate = new java.sql.Date(new java.util.Date().getTime());
Or:
#XmlJavaTypeAdapters({
#XmlJavaTypeAdapter(value=MyDateAdapter.class,type=java.sql.Date.class)
})
package mingler.tracker.ejb.client;
Instead of both.