how to read XML file using xml reader? - c#-4.0

Question 1: Assume that i am reading XmlNodeType.Text and I would like to know its tag node name. How do you do that without moving cursor up or down? Also How can I know parent tag of current node tag?
Question 2: Assume that I am reading xml file and I would like to start at particular node tag. How can do that?
Question 3: if you have xsd file, is there easy way to upload xml file? I am using C# 3.5 .net and sql server 2008.
This is what i wrote so far:
XmlTextReader reader = new XmlTextReader("datafile.xml");
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
Console.Write(reader.Name);
}
else if (reader.NodeType == XmlNodeType.Text)
{
Console.Write("/"+reader.Name+"/" + reader.Value+"/");
}
else
{
if (reader.NodeType == XmlNodeType.EndElement)
{
Console.WriteLine(reader.Name);
Console.ReadLine();
}
}
}
reader.Close();
Please let me know if you need more clarification

XmlReader is stateless and only retains information about the current node, so if you are reading the content of an element and wish to know the elements name you need to make sure that when you read the start element node you somehow retain the element name.
Again if you want to know the name of the parent element you need to retain this information / state yourself as you read through the xml document.
If you wish to start reading at a particular node you should go through and read the xml document node by node until you read the node you wish to start at.
Ultimately reading xml via the XmlReader class is more difficult than the alternatives, generally speaking you would only use XmlReader if the the xml document is very large, in most other cases using one of the alternatives:
Linq to XML
The XmlDocument class
Using XSD.exe to generate a .Net class from a XSD file that can be used to serialise and deserialise xml via the XmlSerializer class.
For more information see XML Serialization in the .NET Framework
If you really want to use XmlReader then you should read Using the XmlReader Class .

Related

No insertion orderr is preserved while converting from xml to json using org.json.XML.toJSONObject(xmlStirng)

I am using a dynamic data structure for my project. So instead of a predefined class I am using java.util.LinkedHashMap to store my dynamic data and preserve my insertion order as well.
I am able to convert the map to json and get the map and back from Json using ``.
fasterxml.jackson.databind.ObejctMapper mapper;
LinkedHashMap<String, Object> map =
mapper.readValue(json, new TypeReference<LinkedHashMap<String, Object>>() {});
String json = mapper.writeValueAsString(map);
I am trying to do some XSLT transformation on my map data. So I also need to transform from xml to map and map to xml. As there is no direct method to convert these I wrote my own utility for map to xml.
and to convert from xml to map I used -> org.json.JSONObject. I first convert the xml to json using
org.json.XML.toJSONObject(xmlstring)
and can convert the json to map easily using object mapper.
But the problem here is I am loosing the insertion order which is crucial for my data.
How can I convert my data from xml to json so that the insertion order is preserved.
Thats a superb idea to use LinkedHashMap for dynamic data structure.
However JSONObject internally uses HashMap to create the json. So it looses the insertion order.
public JSONObject() {
// HashMap is used on purpose to ensure that elements are unordered by
// the specification.
// JSON tends to be a portable transfer format to allows the container
// implementations to rearrange their items for a faster element
// retrieval based on associative access.
// Therefore, an implementation mustn't rely on the order of the item.
this.map = new HashMap<String, Object>();
}
So If you can override the JSONObject your problem will be solved.
Enjoy!!!
You don't need to change the jar. You just need to create a new class with the same name of the class inside the jar and also have to create the new classes those are dependent on the class.
You need to copy the code from the jar class to your new class and tweek.
then access that class from you code by changing the import statement.

FileDocument with UIManagedDocument/core data

When using SwiftUI to create a document based app, the default document type is to subclass FileDocument.
All examples lead to simple value types to be used in this document type.
I'm looking to create a UIManagedDocument in SwiftUI but there doesn't seem to be any mention of using FileDocument with core data. I noticed a ReferenceFileDocument but this leads to no examples either...
Has anyone had any experience of using either SwiftUI document type for core data based documents?
After some more months, I came across this question once again.
Since my last comment on September 18th, I've worked myself on solving the puzzle of building a SwiftUI document-based app using Core Data.
Looking more in-depth I learned that the UIManagedDocument (respectively its parent UIDocument) infrastructure is really close/similar to what SwiftUI tries to implement. SwiftUI even uses UIDocument in the background to do "its magic". UIDocument and UIManagedDocument are simply some more archaic remnants of times where Objective-C was the dominant language. There was no Swift and there were no value-types.
In general I can give you the following tips to solve your challenge using Core Data within a UIManagedDocument:
first of all, if you want to use Core Data, you will have to use a package/bundle based document format. This means your UTType will have to conform to .package (=com.apple.package in your Info.plist file). You won't be able to make Core Data work with only a plain file document.
extension UTType {
static var exampleDocument: UTType {
UTType(exportedAs: "com.example.mydocument", conformingTo: .package)
}
}
use a ReferenceFileDocument based class to build a wrapper document for your UIManagedDocument. This is necessary because you will have to know about the time when the object is released. In deinit you will have to call managedDocument.close() to ensure the UIManagedDocument is properly closed and no data is lost.
the required function init(configuration:) is going to be called when an existing document is opened. Sadly, it is of no use when working with UIManagedDocument because we have only access to the FileWrapper of the document and not the URL. But the URL is what you need to initialize the UIManagedDocument.
the required function snapshot(contentType:) and fileWrappper(snapshot:, configuration:) is only used to create a new empty document. (This is because we won't use the SwiftUI integrated UndoManager but the one from UIManagedDocument respectively Core Datas NSManagedObjectContext.) Therefore it is not relevant what your type for Snapshot is. You can use a Date or Int because the snapshot taken with the first function is not what you are going to write in the second function.
The fileWrappper(snapshot:, configuration:) function should return the file structure of an empty UIManagedDocument. This means, it should contain a directory StoreContent and an empty file with the filename of the persistent store (default is persistentStore) as in the screenshot below.
The persistentStore-shm and persistentStore-wal files are going to be created automatically when Core Data is starting up, so we do not have to create them in advance.
I am using the following expression to create the FileWrapper representing the document: (MyManagedDocument is my UIManagedDocument subclass)
FileWrapper(directoryWithFileWrappers: [
"StoreContent" : FileWrapper(directoryWithFileWrappers: [
MyManagedDocument.persistentStoreName : FileWrapper(regularFileWithContents: Data())
])
])
above steps allow us to create an empty document. But it still cannot be connected to our UIManagedDocument subclass, because we have no idea where the document (represented by the FileWrapper we have created) is located. Luckily SwiftUI is passing us the URL of the currently opened document in the ReferenceFileDocumentConfiguration which is accessible in the DocumentGroup content closure. The property fileURL can then be used to finally create and open our UIManagedDocument instance from the wrapper. I'm doing this as follows: (file.document is an instance of our ReferenceFileDocument class)
DocumentGroup(newDocument: { DemoDocument() }) { file in
ContentView()
.onAppear {
if let url = file.fileURL {
file.document.open(fileURL: url)
}
}
}
in my open(fileURL:) method, I then instantiate the UIManagedDocument subclass and call open to properly initialize it.
With above steps you will be able to display your document and access its managedObjectContext in a view similar to this: (DocumentView is a regular SwiftUI view using for example #FetchRequest to query data)
struct ContentView: View {
#EnvironmentObject var document: DemoDocument
var body: some View {
if let managedDocument = document.managedDocument {
DocumentView()
.environment(\.managedObjectContext, managedDocument.managedObjectContext)
} else {
ProgressView("Loading")
}
}
}
But you will soon encounter some issues/crashes:
You see the app freeze when a document is opened. It seems as if UIManagedDocument open or close won't finish/return.
This is due to some deadlock. (You might remember, that I initially told you that SwiftUI is using UIDocument behind the scene? This is probably the cause of the deadlock: we are running already some open while we try to execute another open command.
Workaround: run all calls to open and close on a background queue.
Your app crashes when you try to open another document after having previously closed one. You might see errors as:
warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'Item' so +entity is unable to disambiguate.
warning: 'Item' (0x6000023c4420) from NSManagedObjectModel (0x600003781220) claims 'Item'.
warning: 'Item' (0x6000023ecb00) from NSManagedObjectModel (0x600003787930) claims 'Item'.
error: +[Item entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
After having debugged this for some hours, I learned that the NSManagedObjectModel (instantiated by our UIManagedDocument) is not released between closing a document and opening another. (Which, by good reason, is not necessary as we would use the same model anyway for the next file we open). The solution I found to this problem was to override the managedObjectModel variable for my UIManagedDocument subclass and return the NSManagedObjectModel which I'm loading "manually" from my apps bundle. I suppose there are nicer ways to do this, but here is the code I'm using:
class MyManagedDocument: UIManagedDocument {
// We fetch the ManagedObjectModel only once and cache it statically
private static let managedObjectModel: NSManagedObjectModel = {
guard let url = Bundle(for: MyManagedDocument.self).url(forResource: "Model", withExtension: "momd") else {
fatalError("Model.xcdatamodeld not found in bundle")
}
guard let mom = NSManagedObjectModel(contentsOf: url) else {
fatalError("Model.xcdatamodeld not load from bundle")
}
return mom
}()
// Make sure to use always the same instance of the model, otherwise we get crashes when opening another document
override var managedObjectModel: NSManagedObjectModel {
Self.managedObjectModel
}
}
So this answer has become really lengthy, but I hope it is helpful to others struggling with this topic. I've put up this gist with my working example to copy and explore.

JAXB: How to list identical child elements having different tags names

I have an XML in following format:
<servers>
<server_1>
<name>S1</name>
<user>User1</user>
<pass>pass1</pass>
</server_1>
<server_2>
<name>S2</name>
<user>User2</user>
<pass>pass2</pass>
</server_2>
<server_3>
<name>S3</name>
<user>User3</user>
<pass>pass3</pass>
</server_3>
</servers>
There can be multiple child elements under servers. And I am having trouble figuring out how to parse these using JAXB unmarshel. If the child would have identical name I could have just unmarshelled them into a list.
I also looked at #XMLAnyElement annotation which would allow me to have these elements into a list but I was facing some type cast issues since doing that gives ElementNSImpl and then I'd have to convert it to a simple Server entry class. Is that the only way to process such case?
Can't I use regex in #XMLElement's name field to populate such entries ignoring the different tags (server_1 , server_2 etc) or any other way to disregard the different child element tags.
I was using this guide to understand XMLAnyElement behavior: http://blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html but this is not really for my kind of use case.
Another approach I was thinking is of modifying the parent xml itself and replacing server_X type tags with server using Java FileReaders before unmarshling the XML file.
I will appreciate help or pointing me in right direction.
Edit: I see that following code works-
..
..
#XmlAnyElement
public List<ElementNSImpl> getServer() {
return server;
}
..
..
public void printElem() {
if(server!=null) {
for(ElementNSImpl serverEntry :server) {
NodeList nodeList= ftpEntry.getChildNodes();
System.out.println("length:"+nodeList.getLength());
for(int i=0;i<nodeList.getLength()-1;i++)
System.out.println(nodeList.item(i).getNodeName()+" :"+nodeList.item(i).getTextContent());
}
}
}
But java gives warning message on using ElementNSImpl directly:
Access restriction: The type 'ElementNSImpl' is not API (restriction on required library 'C:\Program Files (x86)\Java\jre1.8.0_171\lib\rt.jar')
So I am not sure if it is okay to use ElementNSImpl like this.

Create docx file from a template file in java

I need to create docx files based on a templates.
The template should contain the place holders and I should be able to fill the the place holders from java .
Is it possible to do it , If so suggest me the good and efficient way to do it .
A little late for the original question, but if anyone else needs to dynamically create docx documents from templates, you might want to have a look at the DocxStamper Java library which I created on top of docx4j.
It allows to use the Spring Expression Language in docx templates and you can create a document out of a template with a couple lines like this:
MyData data = ...; // your own POJO containing the data
InputStream template = ...; // InputStream to the template file
OutputStream out = ...; // OutputStream to the resulting document
DocxStamper stamper = new DocxStamperConfiguration()
.build();
stamper.stamp(template, context, out);
out.close();
As discussed elsewhere before, there are 3 basic approaches:
BEST: content control data binding
cheap/cheerful: Variable replacement (ie magic strings on the document surface), but brittle (the split run problem)
LEGACY: MERGEFIELD with or without other field codes.
Docx4j supports all three approaches, but we generally recommend content control databinding, since it aligns with Microsoft's direction (as best can be ascertained), and is most powerful.
You'll want to consider the technical skills of your template authors.
See https://github.com/centic9/poi-mail-merge for a simple "Variable replacement" method. It does not work if one replacement-string has multiple formats applied, but does work well for simple cases where the template is carefully crafted.
Basically it reads the template and data from CSV or an Excel file and then merges it into multiple result files, one for each line of data.
It works on the DOCX XML content, so is not fully using Apache POI XWPF support, but this way formatting and other things from the template are used as expected without the need for full support for everything in Apache POI (which has DOCX support still as part of the "scratchpad" component as support is not considered fully done yet).
You can use Word template with following syntax of LINQ Reporting to achieve your requirements using Aspose.Words for Java.
<< tag_name [expression] -switch1 -switch2 ...>>
A tag body typically consists of the following elements:
A tag name
An expression surrounded by brackets
A set of switches available for the tag, each of which is preceded by the “-“ character
Assume, that you have the Sender class defined in your application as follows:
public class Sender {
public Sender(String name, String message) {
_name = name;
_message = message;
}
public String getName() {
return _name;
}
public String getMessage() {
return _message;
}
private String _name;
private String _message;
}
To produce a report containing a message of a concrete sender on its behalf, you can use a template document with the following content.
<<[s.getName()]>> says: "<<[s.getMessage()]>>."
To build a report from the template, you can use the following source code.
Document doc = new Document(getMyDir() + "temp_HelloWorld.docx");
Sender sender = new Sender("LINQ Reporting Engine", "Hello World");
ReportingEngine engine = new ReportingEngine();
engine.buildReport(doc, sender, "s");
doc.save(getMyDir() + "out.docx");
I work with Aspose as Developer evangelist.

Is it possible to parse sub-trees with Groovy XMLSlurper

Does anyone know whether it is possible to utilise XMLSlurper in a fashion that means individual sub-trees can be pulled from a very large XML document and processed individually?
Imagine you've got a huge XML feed containing a root element that has thousands of direct child elements that you can process individually. Obviously, reading the whole document into memory is a no-no but, as each child of the root is itself modestly sized, it would be nice to stream through the document but apply XMLSlurper niceness to each of the child elements in turn. As each child element is processed, garbage collection can clean up memory used to process it. In this way we get the great ease of XMLSlurper (such concise syntax) with the low memory footprint of streaming (e.g. SAX).
I'd be interested to know if anyone has ideas on this and/or whether you've come across this requirement yourselves.
Initializing an XmlSlurper instance means, calling one of its overloaded parse(..) methods (or the parseText(String) method). Upon this call, XmlSlurper will (use SAX events, at least, to) construct an in-memory GPathResult that holds the complete information on the XML elements and attributes, and their structure.
So, no, the XmlSlurper does not provide an API to parse XML document portions, only.
What can be done is, extending XmlSlurper, overwriting the parse*(..) methods, pre-processing the XML by using a custom SAX handler, gathering the desired portions of XML, and forwarding these to one of the XmlSlurper.parse*(..) methods.
You can use StAX API together with XmlSlurper to parse subtrees.
// Example of using StAX to split a large XML document and parse a single element using XmlSlurper
import javax.xml.stream.XMLInputFactory
import javax.xml.stream.XMLStreamReader
import javax.xml.transform.Transformer
import javax.xml.transform.TransformerFactory
import javax.xml.transform.sax.SAXResult
import javax.xml.transform.stax.StAXSource
def url = new URL("http://repo2.maven.org/maven2/archetype-catalog.xml")
url.withInputStream { inputStream ->
def xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream)
def transformer = TransformerFactory.newInstance().newTransformer()
while (xmlStreamReader.hasNext()) {
xmlStreamReader.next()
if (xmlStreamReader.isStartElement() && xmlStreamReader.getLocalName() == 'archetype') {
// Example of splitting a large XML document and parsing a single element with XmlSlurper at a time
def xmlSlurper = new XmlSlurper()
transformer.transform(new StAXSource(xmlStreamReader), new SAXResult(xmlSlurper))
def archetype = xmlSlurper.document
println "${archetype.groupId} ${archetype.artifactId} ${archetype.version}"
}
}
}

Resources