SAX parser not taking multiple attributes for a tag - xml-parsing

I want to parse the following XML file and print the list of all the attributes for the tag book. I am parsing with SAX parser. The problem is it is printing only the first attributes. The other attribute is not getting printed.
The XML is as follows.
<?xml version="1.0"?>
<catalog>
<book id="bk101" action="lock">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
</book>
</catalog>
How should I write the code for printing all the attributes for the tag book.

The SAX callback for startElement can look like this. Here the attributes are parsed in a loop:
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts)
throws SAXException
{
System.out.print("<"+qName);
for(int i=0; i<atts.getLength(); i++) {
System.out.print(" "+atts.getQName(i)+"=\""+atts.getValue(i)+"\"");
}
System.out.println(">");
}

Related

.NET Core: How to Output String from StreamReader as XML

Doing a project in .Net Core 2, using MVC, I'm attempting to incorporate a project from GitHub that generates the XML for an RSS feed. It is TAlex.RSSFeedGenerator.
To generate the actual document, the FeedGenerator's only option is serializing its RSS object to a MemoryStream:
public void Generate(Rss rss, Stream output)
{
XmlSerializer serializer = new XmlSerializer(typeof(Rss));
serializer.Serialize(output, rss);
}
So FeedGenerator has already serialized the RSS content as XML in Stream, and I want to return that content as XML from an MVC Controller ( return Ok(content_here) ).
How can I do this?
As incorporated originally / currently:
var rss = new Rss();
// ...
var RssFeedGenerator = new FeedGenerator();
var output = new MemoryStream();
RssFeedGenerator.Generate(rss, output);
output.Position = 0;
var sreader = new StreamReader(output);
return Ok(sreader.ReadToEnd());
This puts out a string and is seen as a string by the browser. It is not seen as XML or RSS.
The MVC Controller is defined and decorated like so:
[HttpGet()]
[Produces("text/xml")]
public async Task<IActionResult> GetAsync() {...}
So, I need the string that is already an XML document to be recognized as an XML document, not a string. My goal is also to send the contents as a response directly, not save it to a file and then have to redirect the user to that file or have to have Ok() read from the file.
Also, I can't send the MemoryStream directly to Ok(), because I get an error that one can't access a closed stream.
The browser is currently showing this:
<string><?xml version="1.0" encoding="utf-16"?> ... </string>
(Originally, it was properly decoding the HTML entities, so you'd see:
<string><?xml version="1.0" encoding="utf-16"?> ... </string>
but now it's not even doing that.)
Thanks for clarifying.
Please return ContentResult in order to see the RSS XML. You can have "application/xml" or "application/RSS+XML" or "text/xml"
public async Task<IActionResult> GetAsync()
{
string rssFeed = "<?xml >...";
return new ContentResult
{
Content = rssFeed,
ContentType = "application/RSS+xml"
};
}

How to pass xml content as an string to jaxb parser

I have an xml content as string how can i pass that to jaxb parser to populate the pojo class
<?xml version="1.0" encoding="UTF-8"?><breakfast_menu<food>
<name>Belgian Waffles</name><food>
To pass XML content, you need to wrap the content in a Reader, and unmarshal that instead:
JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader("xml string here");
Person person = (Person) unmarshaller.unmarshal(reader);

Checking HTML document with REST Assured

I'm trying to use REST Assured to check some properties on an HTML document returned by my server. An SSCCE demonstrating the problem would be as follows:
import static com.jayway.restassured.path.xml.config.XmlPathConfig.xmlPathConfig;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import com.jayway.restassured.path.xml.XmlPath;
public class HtmlDocumentTest {
#Test
public void titleShouldBeHelloWorld() {
final XmlPath xml = new XmlPath("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
+ "<head><title>Hello world</title></head><body></body></html>")
.using(xmlPathConfig().with().feature("http://apache.org/xml/features/disallow-doctype-decl", false));
assertThat(xml.get("//title[text()]"), is("Hello world"));
}
}
Now, this attempt ends in com.jayway.restassured.path.xml.exception.XmlPathException: Failed to parse the XML document caused by, off all the possible errors, java.net.ConnectException: Connection timed out after some 30 seconds or so!
If I remove the line with the xmlPathConfig().with().feature(...) the test fails immediately due to DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true..
If I remove the doctype line from the document the parsing succeeds but the test fails on an assertion error, "Expected: is "Hello world" but: was <Hello worldnull>" -- however, that's a different problem, obviously (but feel free to give instructions on that one, too...). And removing the doctype isn't an option for me anyway.
So, question: how do you check properties of an HTML document with a doctype using REST Assured? It says in the documentation that "REST Assured providers predefined parsers for e.g. HTML, XML and JSON.", but I cannot seem to find any examples on how exactly to activate and work with that HTML parser! There's no "HtmlPath" class like there's XmlPath, for example, and that timeout exception is very puzzling...
I checked your code. The thing is that XmlPath of Restassured isn't Xpath, but uses a property access syntax. If you add a body content to your sample HTML you will see that your XPath doesn't do much. The actual name of the query language is GPath. The following example works, note also the use of CompatibilityMode.HTML, which has the right config for you need:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.jayway.restassured.path.xml.XmlPath;
import com.jayway.restassured.path.xml.XmlPath.CompatibilityMode;
public class HtmlDocumentTest {
#Test
public void titleShouldBeHelloWorld() {
XmlPath doc = new XmlPath(
CompatibilityMode.HTML,
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
+ "<head><title>Hello world</title></head>"
+ "<body>some body"
+ "<div class=\"content\">wrapped</div>"
+ "<div class=\"content\">wrapped2</div>"
+ "</body></html>");
String title = doc.getString("html.head.title");
String content = doc.getString("html.body.div.find { it.#class == 'content' }");
String content2 = doc.getString("**.findAll { it.#class == 'content' }[1]");
assertEquals("Hello world", title);
assertEquals("wrapped", content);
assertEquals("wrapped2", content2);
}
}
If you're using the DSL (given/when/then) then XmlPath with CompatibilityMode.HTML is used automatically if the response content-type header contains a html compatible media type (such as text/html). For example if /index.html contains the following html page:
<html>
<title>My page</title>
<body>Something</body>
</html>
then you can validate the title and body like this:
when().
get("/index.html").
then().
statusCode(200).
body("html.title", equalTo("My page"),
"html.body", equalTo("Something"));
Here is sample code with the latest rest assured apis, i.e. io.restassured and not the older jayway.restassured. The explanation for the code is in the code comments.
//Demo for an api which returns a json string inside html. The json string is just an array of objects.
import io.restassured.RestAssured;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import java.util.List;
import static io.restassured.RestAssured.*;
public void testMyApi() {
Response response =
when().
get("www.myapi.com/data").
then().
extract().
response();
String bodyTxt = response.htmlPath().getString("body");//Get the body element of the html response.
JsonPath jsonObj = new JsonPath(bodyTxt);//helps us to find things in a json string.
List<String> rootItems = jsonObj.getList("$");//get root element of the json part.
System.out.println(rootItems);
}

Grails XML converters - write CDATA

Is writing CDATA from GRAILS converters possible? I have a requirement of writing CDATA for some XML elements in a GRAILS app. After running through the grails code in debugger, it looks like the XMLStreamWriter is not accessible. Any recommendations?
there's no possibility to add cdata via xml converters. you can use StreamingMarkupBuilder:
Generate CDATA inside of tag using StreamingMarkupBuilder
or, have a nice uglyhack, copying '.chars' method from groovy converter definition right in your code, writing chars unescaped:
converter.startNode('property')
converter.attribute('name', propertyName)
converter.startNode('value')
//converter.chars("<![CDATA[" + propertyValue + "]]>")
//as chars in xml converter go escaped, had to rewrite the method here:
converter.checkState();
try {
if (converter.writer.mode == TAG) {
converter.writer.endStartTag();
}
converter.writer.mode = CONTENT;
//we put the data unescaped:
converter.writer.writer.unescaped().write("<![CDATA[" + propertyValue + "]]>");
}
catch (Exception e) {
throw ConverterUtil.resolveConverterException(e);
}
//-----------------
converter.end()
converter.end()

IXmlSerializable and Root Element Prefix

I have looked everywhere and not a single response is valid or the question is just slightly off to the point of not getting me the answer I need. Given all the searches I have looked for there seems to be one MASSIVE flaw in .Net's implementation of xml serialization.
Default:
[XmlRoot("root", Namespace="http://myclass.org/")]
public class MyClass
{
}
void Main() {
XmlSerializer ser = new XmlSerializer(typeof(MyClass));
XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
xsn.Add("mc", "http://myclass.org/");
ser.Serialize(new StreamWriter(Console.Out), new MyClass(), xsn);
}
OUTPUT:
<?xml version="1.0"?>
<mc:root xmlns:mc="http://myclass.org/">
</mc:root>
IXmlSerializable:
[XmlRoot("root", Namespace="http://myclass.org/")]
public class MyClass : IXmlSerializable
{
public XmlSchema GetSchema() {return null;}
public void ReadXml(XmlReader reader) {}
public void WriteXml(XmlWriter writer) {}
}
void Main() {
XmlSerializer ser = new XmlSerializer(typeof(MyClass));
XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
xsn.Add("mc", "http://myclass.org/");
ser.Serialize(new StreamWriter(Console.Out), new MyClass(), xsn);
}
OUTPUT:
<?xml version="1.0"?>
<root xmlns="http://myclass.org/">
</root>
WHY!
How do we fix this?
This is essential to figure out because without custom processing I will be forced to double step it, and process the serialized xml into an XmlDocument to fix this glitch. and yes, this HAS to be a glitch. I can work around everything else EXCEPT the root element.
I am not the only one who needs to know how to do this.
Thanks
Jaeden "Sifo Dyas" al'Raec Ruiner

Resources