Is it possible to generate plain-old XML using Haml? - ruby-on-rails

I've been working on a piece of software where I need to generate a custom XML file to send back to a client application. The current solutions on Ruby/Rails world for generating XML files are slow, at best. Using builder or event Nokogiri, while have a nice syntax and are maintainable solutions, they consume too much time and processing.
I definetly could go to ERB, which provides a good speed at the expense of building the whole XML by hand.
HAML is a great tool, have a nice and straight-forward syntax and is fairly fast. But I'm struggling to build pure XML files using it. Which makes me wonder, is it possible at all?
Does any one have some pointers to some code or docs showing how to do this, build a full, valid XML from HAML?

Doing XML in HAML is easy, just start off your template with:
!!! XML
which produces
<?xml version='1.0' encoding='utf-8' ?>
Then as #beanish said earlier, you "make up your own tags":
%test
%test2 hello
%item{:name => "blah"}
to get
<test>
<test2>hello</test2>
<item name='blah'></item>
</test>
More:
http://haml.info/docs/yardoc/file.REFERENCE.html#doctype_

%test
%test2 hello
%item{:name => "blah"}
run it through haml
haml hamltest.haml test.xml
open the file in a browser
<test>
<test2>hello</test2>
<item name='blah'></item>
</test>
The HAML reference talks about html tags and gives some examples.
HAML reference

This demonstrates some things that could use useful for xml documents:
!!! XML
%root{'xmlns:foo' => 'http://myns'}
-# Note: :dashed-attr is invalid syntax
%dashed-tag{'dashed-attr' => 'value'} Text
%underscore_tag Text
- ['apple', 'orange', 'pear'].each do |fruit|
- haml_tag(fruit, "Yummy #{fruit.capitalize}!", 'fruit-code' => fruit.upcase)
%foo:nstag{'foo:nsattr' => 'value'}
Output:
<?xml version='1.0' encoding='utf-8' ?>
<root xmlns:foo='http://myns'>
<dashed-tag dashed-attr='value'>Text</dashed-tag>
<underscore_tag>Text</underscore_tag>
<apple fruit-code='APPLE'>Yummy Apple!</apple>
<orange fruit-code='ORANGE'>Yummy Orange!</orange>
<pear fruit-code='PEAR'>Yummy Pear!</pear>
<foo:nstag foo:nsattr='value'></foo:nstag>
</root>
Look at the Haml::Helpers link on the haml reference for more methods like haml_tag.
If you want to use double-quotes for attributes,
See: https://stackoverflow.com/a/967065/498594
Or outside of rails use:
>> Haml::Engine.new("%tag{:name => 'value'}", :attr_wrapper => '"').to_html
=> "<tag name=\"value\"></tag>\n"

Haml can produce XML just as easily as HTML (I've used it for FBML and XHTML). What problems are you having?

I've not used HAML, but if you can't make it work another option is Builder.

what about creating the xml header, e.g. <?xml version="1.0" encoding="UTF-8"?>
?

It should be possible. After all you can create plain old XML with Notepad.

Related

SAXParseException when using restassured

I am trying to verify a XML response with rest-assured like this:
.then().body("some.xml.path", is("abc"));
However, what I get is a SAXParseException:
DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.]
Response starts like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cXML.org/schemas/cXML/1.2.021/cXML.dtd">
<cXML ...
Why am I getting this exception? What should I change?
I am using version 3.2.0 of rest-assured.
A similar question has been answered here. In short, the answer describes to use disableLoadingOfExternalDtd() to have RestAssured ignore the Document Type Definition in your XML.
Normally, the DTD would describe (using the external definition) the structural layout of the element defined as cXML.

Simple and quick way to parse an XML file in iOS7

I have a simple XML file like this
<?xml version="1.0"?>
<catalog>
<timezone>
<name>UTC-11:00</name>
<place>
<value>American Samoa</value>
<value>Samoa</value>
</place>
</timezone>
<timezone>
<name>UTC-10:00</name>
<place>
<value>Honolulu</value>
<value>Tahiti</value>
</place>
</timezone>
</catalog>
What is the canonical/standard way to parse this in iOS? I want to save "names" and "places" for each name.
NSXMLParser is already built in. You should look at this article for a more thorough comparison.
http://www.raywenderlich.com/553/xml-tutorial-for-ios-how-to-choose-the-best-xml-parser-for-your-iphone-project
It is NSXMLParser. Official documentation

Validating XML with an in-memory DTD in C using libxml2

I need to validate XML using DTD stored in memory, i.e. something like the following:
static const char *dtd_str = "<!ELEMENT ...>";
xmlDtdPtr dtd;
dtd = xmlParseMemoryDtd(dtd_str);
XML_PARSE_DTDVALID parser option allows to validate DTD embedded into XML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE some_tag[
<!ELEMENT some_tag ...>
...
]>
<some_tag>...</some_tag>
So a workaround is to modify in-memory XML. Things become more complicated with
a parser used in "push mode". In push mode we have to detect whether the XML
declaration (<?xml ...?>), or start of the root element, then put our inline
DTD between them.
Could you suggest better solution?
EDIT
A workaround is to validate parsed XML posteriori as Daniel(_DV) suggested below.
Example: main.c, response.xml.
But I was searching for way to "embed" a DTD and validate XML "on-the-fly" while libxml2 parses XML chunk-by-chunk.
The following aproach doesn't work for me:
xmlCtxtUseOptions(ctxt, XML_PARSE_NOENT | XML_PARSE_NOWARNING | XML_PARSE_DTDVALID);
ctxt->sax->internalSubset = ngx_http_file_chunks_sax_internal_subset;
ctxt->sax->externalSubset = NULL;
$ ./parsexml
validity error : Validation failed: no DTD found !
<response>
^
Document is not valid
xmlValidateDtd allows to do DTD validation a posteriori of an already parsed XML document
to make sure it validates against the DTD. This will not use the internal subset...
http://xmlsoft.org/html/libxml-valid.html#xmlValidateDtd
See xmllint.c code in libxml2 for a full example of how to use it,
Daniel

retrieve xml file using nsxmlparser in ios

i am getting problem while reading xml files through nsxmlparser in ios,
<PRODUCTS>
<PRODUCTSLIST>
<PRODUCTDETAILS>
<headertext> test header </headertext>
<description><b style="font-size: x-small;">product, advantages</b></description>
</PRODUCTDETAILS>
</PRODUCTSLIST>
</PRODUCTS>
while i read the file using nsxmlparser i am able to get value(test header) for headertext but the description attribute value contains html tags so i cant able to get the result (<b style="font-size: x-small;">product, advantages</b>)i am getting result as empty
How can i get the result as((<b style="font-size: x-small;">product, advantages</b>)) for description attribute?
Speaking from a developers perspective I would not recommend using NSXMLParser due to it's laborious way to parse XML Files. There is a great write up about choosing the right XML Parser.
I use KissXML quite often.
You can find a quit tutorial of using it here.
Hope this helps.
Your problem is that the "b" tag is considered part of the XML structure, try escaping the '<' and '>' characters of the 'b' tag:
#"<b style=\"font-size: x-small;>product, advantages</b>"
see here

Create xml-stylesheet PI with Rails XMLBuilder

I want to attach an xslt stylesheet to an XML document that I build with XMLBuilder. This is done with a Processing Instruction that looks like
<?xml-stylesheet type='text/xsl' href='/stylesheets/style.xslt' ?>
Normally, I'd use the instruct! method, but :xml-stylesheet is not a valid Ruby symbol.
XMLBuilder has a solution for this case for elements using tag! method, but I don't see the equivalent for Processing Instructions.
Any ideas?
You do it like this:
xm.instruct! 'xml-stylesheet', {:href=>'/stylesheets/style.xslt', :type=>'text/xsl'}
Just add that line right after
xm.instruct! :xml, {:encoding=>"your_encoding_type"}
and before the rest of your document output code and you should be good to go.
I'm not sure this will solve your problem since I don't know the instruct! method of that object, but :'xml-stylesheet' is a valid ruby symbol.
If using the atom_feed helper, you can pass this in the instruct option:
atom_feed(instruct: {
'xml-stylesheet' => {type: 'text/xsl', href: 'styles.xml'}
}) do |feed|
feed.title "My Atom Feed"
# entries...
end
Which results in (showing only first 3 lines):
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="styles.xml"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">

Resources