Set XmlEncoding to Dom Document in Java - dom

I need set the XmlEncoding (UTF-8) in a Dom Document object without use a Transformer with his "setOutputProperty(OutputKeys.ENCODING, "UTF-8")" method.
I don't want obtain the XML string using the Transform object because I am using a Xades XMLSignature library which uses a Document object to sign.
The problem is that for a Dom Document created as follow, his getXmlEncoding() method returns null.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.newDocument();
document.getXmlEncoding(); //Returns null
But after apply the following code, the XmlEncoding methoth of the new DOM Document returns UTF-8 (requeriment for my xades library).
It's because the transformation process has added the encoding somehow.
For performance reasons I want to avoid to execute this code.
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
DOMSource source = new DOMSource(document);
Writer writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(source, result);
String xml = writer.toString();
InputStream stream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document newDocument = dbf.newDocumentBuilder().parse(inputStream);
newDocument.getXmlEncoding(); //returns "UTF-8"
How I can create the Dom Document with the prolog information?

You could try using Apache Axiom's DOM implementation. It implements both the DOM API and Axiom's own API, which actually allows setting the XML encoding. Simply add axiom-dom to your project and use the following instruction to get a DocumentBuilderFactory:
DocumentBuilderFactory factory = ((DOMMetaFactory)OMAbstractFactory.getMetaFactory(OMAbstractFactory.FEATURE_DOM)).newDocumentBuilderFactory();
You can then set the XML encoding on a document as follows:
((OMDocument)document).setXMLEncoding("utf-8");
The rest of your code remains unchanged and can continue using the DOM API.

Related

How to convert SinkRecord to JSON string?

Imagine myAPICreate requires a JSON string.
public void put(Collection<SinkRecord> collection) {
for (SinkRecord record : collection) {
JSONObject recordJson = toJSON(record.value());
String recordJsonString = recordJson.toString();
myAPICreate(recordJsonString);
}
}
toJSON is a helper I have defined which just takes the record and returns a JSONObject.
JSONObject json = new JSONObject()
.put("a", record.getString("a"))
.put("b", record.getString("b"))
.put("c", record.getString("c"));
I feel like I might be doing a lot of redundant work here. Is it necessary to have the code in put convert it to JSON or is there a way to use the converters so that record already comes in as JSON or a JSON string? Then I can just pass myAPICreate(record.value().toString()) without having to manually do it?
When you create a SinkRecord, you have a key & value schema w/ a key and value Object. Those objects should be Struct instances that must be created with the matching Schema
In the Connector configuration, you would then use JSONConverter (or other converter) to get the serialized output

Use GuidRepresentation.Standard with MongoDB

I am implementing a custom IBsonSerializer with the official MongoDB driver (C#). I am in the situation where I must serialize and deserialize a Guid.
If I implement the Serialize method as follow, it works:
public void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
BsonBinaryData data = new BsonBinaryData(value, GuidRepresentation.CSharpLegacy);
bsonWriter.WriteBinaryData(data);
}
However I don't want the Guid representation to be CSharpLegacy, I want to use the standard representation. But if I change the Guid representation in that code, I get the following error:
MongoDB.Bson.BsonSerializationException: The GuidRepresentation for the writer is CSharpLegacy, which requires the subType argument to be UuidLegacy, not UuidStandard.
How do I serialize a Guid value using the standard representation?
Old question but in case someone finds it on google like I did...
Do this once:
BsonDefaults.GuidRepresentation = GuidRepresentation.Standard;
For example, in a Web Application/Web API, your Global.asax.cs file is best place to add it once
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
BsonDefaults.GuidRepresentation = GuidRepresentation.Standard;
//Other code...below
}
}
If you don't want to modify the global setting BsonDefaults.GuidRepresentation (and you shouldn't, because modifying globals is a bad pattern), you can specify the setting when you create your collection:
IMongoDatabase db = ???;
string collectionName = ???;
var collectionSettings = new MongoCollectionSettings {
GuidRepresentation = GuidRepresentation.Standard
};
var collection = db.GetCollection<BsonDocument>(collectionName, collectionSettings);
Then any GUIDs written to the collection will be in the standard format.
Note that when you read records from the database, you will get a System.FormatException if the GUID format in the database is different from the format in your collection settings.
It looks like what's happening is when you are not explicitly passing the GuidRepresentation to BsonBinaryData constructor, it defaults to passing GuidRepresentation.Unspecified and that ultimately maps to GuidRepresentation.Legacy (see this line in the source)
So you need to explicitly pass the guidRepresentation as a third argument to BsonBinaryData set to GuidRepresentation.Standard.
edit: As was later pointed out, you can set BsonDefaults.GuidRepresentation = GuidRepresentation.Standard if that's what you always want to use.

JAXB How to force xsi:type in array of subclasses? (JBoss 4.2.3)

(Please note; i'm completely new to webservices, so the following may be stupid/incorrect but please be patient)
In my WebServices' #WebMethod I'm returning an array of an abstract base class (JAXB annotated entities in JBoss 4.2.3).
Obviously unless the type information is encoded per array element this will fail...
So how do I ensure that JAXB adds the xsi:type attribute?
My WebService interface has the following annotation, and I've tried every legal combination:
#SOAPBinding(style = RPC, parameterStyle = WRAPPED, use = LITERAL)
the methods on this interface take x2 parameters annotated #WebParam(name="...", mode=IN)
Other methods with similar signatures that don't return a heterogeneous array work perfectly.
Some related things:
Looks like JBoss uses the types defined in the method signatures to decide what classes to load into the JAXBContext - if I change the return types to Object[] it throws an error stating that the AbstractBase class "nor any of its super class is known to this context." I've added dummy methods returning the specific subclasses so that the generated WSDL has a list of all of them.
when I try to write tests for this, all is ok for single elements, but JAXB throws an error for array types: unable to marshal type "[LAbstractBase;" as an element because it is missing an #XmlRootElement annotation
From code like that shown below (note: AbstractBase, ConcreteOne and ConcreteTwo all have #XmlRootElement annotations)
private static final Class<?>[] CLASSES_TO_BE_BOUND = new Class<?>[]{
//Note; adding AbstractBase[].class doesn't work either
AbstractBase.class, ConcreteOne.class, ConcreteTwo.class
};
#Test
public void testXsiTypeAttributeIsIncludedInHeterogeneousArray()
{
AbstractBase[] array = new AbstractBase[2];
array[0] = new ConcreteOne();
array[1] = new ConcreteTwo();
Marshaller marshaller = createMarshaller();
StringWriter sw = new StringWriter();
marshaller.marshal(array, sw);
String output = sw.toString();
Assert.assertTrue(output.contains("xsi:type=\""));
}
private Marshaller createMarshaller() throws Exception {
JAXBContext context = JAXBContext.newInstance(CLASSES_TO_BE_BOUND);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
return marshaller;
}
Ideally I'd like to be able to test some bits relating to arrays, but it's far more critical that I can get the type information encoded per element in the JBoss environment.
Edit: Own Answer
JBoss (4.2.3) is doing something clever, but not too clever - it will handle the returning of arrays but not polymorphic arrays. This threw me a bit as I tried to get this way of doing it working in my tests.
Instead of trying to solve the JBoss WebService issue I made my tests more comprehensive - making the array a member of a simple container class and then annotating the array's getter with:
#XmlElementRefs({
#XmlElementRef(type = ConcreteOne.class),
#XmlElementRef(type = ConcreteTwo.class)
})
public AbstractBase[] getItems() { /*...*/ }
Which worked, and returning this in the JBoss WebService also worked! Though I'm using:
#SOAPBinding(style = DOCUMENT, parameterStyle = BARE, use = LITERAL)
So it's not adding the xsi:type attribute, but document nodes are correctly tagged:
<ConcreteOne>...</ConcreteOne>
At some point I'll change the WebService to use RPC as I don't really like the single argument restriction, but for now this is working fine.

Pull generated HTML programmatically vs. a HttpWebRequest

For our newsletter, I generate the final body of the email in a web page and then want to pull that into the body of the email. I found a way to do that with HttpWebRequest.
private string GetHtmlBody(Guid id)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("http://news.domain.com/News/View/{0}", id.ToString()));
HttpWebResponse responce = (HttpWebResponse)request.GetResponse();
System.IO.StreamReader sr = new System.IO.StreamReader(responce.GetResponseStream());
return sr.ReadToEnd();
}
However, I feel there has to be a better way. Can I somehow pull the generated view without making a web call?
You could use MVCContrib for this task.
Or try to roll some ugly code:
public static string ViewToString(string controlName, object viewData)
{
var vd = new ViewDataDictionary(viewData);
var vp = new ViewPage { ViewData = vd };
var control = vp.LoadControl(controlName);
vp.Controls.Add(control);
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
using (HtmlTextWriter tw = new HtmlTextWriter(sw))
{
vp.RenderControl(tw);
}
return sb.ToString();
}
and then:
var viewModel = ...
string template = ViewToString("~/Emails/EmailTemplate.ascx", viewModel);
Assuming the the email code is in the same project as the website, then you should be able to call the action method, get the ActionResult back, then call the ExecuteResult method. The downside is that in order to do it this way, you will need to set it up such that the ExecuteResult will write to a stream that you can take advantage of. In order to do all of this, you will need to mock up some of the classes used by the ControllerContext.
What would probably be a better way (though will likely take more work), is to have the markup you want be generated by an XSLT transform. XSLT is a type of XML document template that can be merged with an XML document that holds data to produce a desired result. If you do this, then you can have your process that sends out emails run the transform as well as have your website run the transform. The advantage of this, is that if you want the markup to be different (i.e. you are redesigning thew newsletter), you will simply need to update the XSLT file and deploy it.
HTH
Finally got a working solution. After finding some proper search terms (thanks to #Darin) any many, many trials I found a solution that works. Putting this in my controller then passing the rendered string into my EmailHelper works great for what I needed.

Transforming data retrieved from LINQ (IQueryable) to XML?

I presume this is possible? Basically i am receiving using LINQ (LINQ2Entities Entity Framework) data and return it to an IQUERYABLE once i this data i need to transform it to XML in a Memory Stream and a physical file on the hard disk - streamwriter??
Does anyone know if this is possible?
Any help really appreciated
Do i need to use LINQtoXML to accomplish this?
Any examples or tutorials anybody knows of would be great.
Thanks again
EDIT
After a little bit of investigation i think i require a XML Serializer for LINQ2Entities / IQueryable??
LINQ to XML is probably the best choice. You can use functional construction to create an XML tree in a single statement, like:
using (ContactEntities context = new ContactEntities()) {
XDocument xml = new XDocument(
new XElement("contacts",
from contact in context.Contacts
orderby contact.ContactId
select new XElement("contact",
new XAttribute("contactId", contact.ContactId),
new XElement("firstName", contact.FirstName),
new XElement("lastName", contact.LastName))));
xml.Save(yourStream);
}
Entity classes are by default Data Contracts, which means that they can be serialized based on the fields they contain:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx
I know this question is a old, but I wanted to show my solution to this problem.
public static string CreateXml<T>(IQueryable<T> thisQueryable)
{
var thisList = thisQueryable.ToList();
var xmlResult = "";
using (var stringWriter = new StringWriter())
{
using (var xmlWriter = new XmlTextWriter(stringWriter))
{
var serializer = new XmlSerializer(typeof(List<T>));
serializer.Serialize(xmlWriter, thisList);
}
xmlResult = stringWriter.ToString();
}
return xmlResult;
}
Basically this just takes your IQueryable<T> and serializes it to XML and returns that XML as a string.
Then you'd basically take that string and....
var xmlDoc = new XmlDocument();
xmlDoc.Load(xmlResult);
Hope this helps for any future visitors.