I'm building a java tool to validate an xml document and build an html report containing the input data and validation results.
I think that a possible way is:
validate XML with XSD
enrich the XML with validation results
transform the enriched XML in the final HTML report (this point is not object of the question)
First and foremost, is this a valid approach? Or there are more suitable ways to get those things done in java?
If this is is a viable solution, how can i implement step 2?
For example, if I start from this input document:
<parent>
<child id="a correct id" type="a correct type"/>
<child id="an incorrect id" type="an incorrect type"/>
</parent>
How can I produce an enriched output document like that:
<parent>
<child id="a correct id" type="a correct type">
<results>
<result>id is correct</result>
<result>type is correct</result>
</results>
</child>
<child id="an incorrect id" type="an incorrect type">
<results>
<result>id is NOT correct</result>
<result>type is NOT correct</result>
</results>
</child>
</parent>
First, there are many ways of going about this. There are other tools like schematron that provide languages for describing validation results, and the ability to transform the results of validation into pretty HTML. There are numerous java packages that actually do schema validation, so most of what you're trying to accomplish should be "glue code". Make sure you don't attempt to do schema validation in your java code.
So next, I'm not sure what your requirements are for wanting to transform the original XML file after validation. Usually you'd dump a validation result set as a separate file. Does the schema for the original XML permit your additions that you're putting in?
In general, if you wanted to transform the original input, you could go about this by writing an XSLT program that takes the validation results file, and the original source file, and then transforms the original file using those validation results. But I don't recommend that because I think your situation might call for a different design that doesn't transform the original file, unless you have more requirements you want to go into more depth about.
Another option would be straightforward DOM manipulation. After validation, you could load the DOM for the input document, manipulate it, then write it back to the same original file.
But seriously -- before you adopt any approach for step 2, make sure that your requirements really call for it.
One approach worth exploring: Xerces-J provides access to the post-schema-validation infoset (PSVI), and can in fact serialize it as XML. For small documents, at least, you may find that XML representation of the PSVI suffices for your purposes.
The PSVI representation made available by Xerces-J (and by xsv) is not, it should be said, anything like an annotated copy of the input. But it can be transformed into a form like the one you show using normal XML processing.
I'm returning to this question after I got some deeper understanding and experience of XSD and XSLT and eventually built my project on that knowledge.
My original question had some misleading points.
My objective was to process an XML with the ONLY objective to produce a corresponding HTML report, containing the XML data in a readable form along with the "validation" results against a set of business rules.
My wrong assumption was that I should necessarily have to validate the XML against an XSD, but that brought me some significant challenges in development:
XSD 1.0 did not fit completely my business rules. So I had to switch to XSD 1.1
then I had to set up an XSD 1.1 compliant validator in java (Xerces2J)
and finally I started thinking on how to build a fine-grained validator based on those premises.
It was at that time that I realized that this process was a little overkill: what I really needed was just a TRANSFORMATION from XML to HTML: the fine-grained validation could have been done inside the transformation process, all together with an XSLT.
To answer my own question in the most generic form:
I would still use XSD for a very basic preliminary validation, and then use XSLT to check for more complex validation rules and enrich the XML.
This is the XSLT to transform the source xml of my own question into the result (still XML).
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="parent">
<xsl:for-each select="child">
<xsl:call-template name="processChildren"/>
</xsl:for-each>
</xsl:template>
<!-- this template processes the children nodes, applying a sample test clause -->
<xsl:template name="processChildren">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
<results>
<xsl:choose>
<xsl:when test="contains(#id,'incorrect')">
<result>id is NOT correct</result>
</xsl:when>
<xsl:otherwise>
<result>id is correct</result>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="contains(#type,'incorrect')">
<result>type is NOT correct</result>
</xsl:when>
<xsl:otherwise>
<result>type is correct</result>
</xsl:otherwise>
</xsl:choose>
</results>
</xsl:copy>
</xsl:template>
<!-- this template copy the contents of the node unaltered -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Related
It's not an duplicate, the problem ist not show an xml in html, rather to show xml with occasional stylesheets for single lines.
i'm looking since hourse for an solution to show xml in a html page with inline css.
Background: Input data is an xml file, what will be compared with another xml file in java. The comparison is processed by org.custommonkey.xmlunit.
Now i like to transform the xml via xslt and the xpathes from the comparison result of xunit.
Input XML (Multilevel, but for this example very simplified, the Field changed by is exemplary for all other fields)
<ROOT>
<MATDETAIL>
<OUTPUT>
<GENERAL>
<CREATED_ON/>
<CREATED_BY>ORIGINAL USER</CREATED_BY>
<LAST_CHNGE/>
<CHANGED_BY>NEW USER</CHANGED_BY>
</GENERAL>
<RETURN>
<TYPE>S</TYPE>
<MESSAGE/>
<LOG_NO/>
<LOG_MSG_NO>000000</LOG_MSG_NO>
</RETURN>
</OUTPUT>
</MATDETAIL>
</ROOT>
XUnit Diff Result XPath
/ROOT[1]/MATDETAIL[1]/OUTPUT[1]/GENERAL[1]/CHANGED_BY[1]/text()[1]
now i will be perfom an translation via xslt (already existing)
my xsl shows like that
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*" mode="unescape"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/ROOT[1]/MATDETAIL[1]/OUTPUT[1]/GENERAL[1]/CHANGED_BY[1]">
<xsl:element name = "span">
<xsl:attribute name="style">font-weight:bold; color:red </xsl:attribute>
<xsl:copy>
<xsl:value-of select = "current()" />
</xsl:copy>
<xsl:text><== Expected: dasda</xsl:text>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
that will give me this result
<ROOT>
<MATDETAIL>
<OUTPUT>
<GENERAL>
<CREATED_ON/>
<CREATED_BY>ORIGINAL USER</CREATED_BY>
<LAST_CHNGE/>
<span style="font-weight:bold; color:red "><CHANGED_BY>NEW USER</CHANGED_BY><== Expected: ORIGINAL USER</span>
</GENERAL>
<RETURN>
<TYPE>S</TYPE>
<MESSAGE/>
<LOG_NO/>
<LOG_MSG_NO>000000</LOG_MSG_NO>
</RETURN>
</OUTPUT>
</MATDETAIL>
</ROOT>
But i'm not able to show this xml in html correctly (with stylesheets).
Either i get no tags, so to see the xml strcuture is very complicated
also i get the xml structure but without stylesheets.
I like to show the result, from comparison with xunit of the two files, in a webservice and this also colored, so you can easy see which elements have change or are incorrectly.
The Problem is to show the full xml + and that seems to be the real problem to color the entries with stylesheets. I can show the xml, but without inline stylesheets, or i can show the styled text but not both.
I already tried to replace lt and gt inside xslt but failed.
I tried to replace lt and gt in the rseult via example java. so every lt and gt are html coded tags. but the result shows very ugly. My colleague has meant that we can not use it in any way.
I tried to style the xml via css > definiton per tag.
But the the structure and fields are full dynamicly, so i cant define css for every tag or field. On the other hand every field can be correct or wrong, depends also on the xml file like to compare. So the field changedby is at the first comparison correct, but on an other comparison its wrong
Unfortunately, alternative implementations are not an option. I have to do this somehow with the means available to me. (Java, XML & XSL, JS, HTML, CSS).
I hope to get good ideas to solute this.
I would like to thank you in advance.
You could use XSLT to transform the xml to HTML so you can display it in a browser. Or build a JS clientside that parses the XML from the server and displays it. This would be something like angularjs.
I'm not sure to understand your request.
If you want to display XML in HTML, you can insert it in the PRE tags : <pre><ROOT>...</ROOT></pre>
If you want to display XML as it could be displayed un an HTML/XML editor you can use Ace : https://ace.c9.io/#nav=about
Other option but not tried : https://highlightjs.org
I'd like to have unclosed html tag as a result of xslt. I'll add closing tag later in xslt. How can I achieve this? This one doesn't compile:
<xsl:when test="$href">
<xsl:text><a href='{$href}'></xsl:text>
</xsl:when>
Thanx
This is the kind of thing that you probably should want to avoid at all costs. I do not know your requirements but you perhaps want a link or a span tag based on something.
In these instances you can use something like this
<xsl:apply-templates select="tag"/>
then 2 templates ie
<xsl:template match="tag">
<span>hello king dave</span>
</xsl:template>
<xsl:template match="tag[#href]">
link text....
</xsl:template>
It's hard to give a definite answer without a better idea of the precise use case, but it's worth noting that you can use match and name on the same <xsl:template>. For example, if you want to produce some particular output for all <tag> elements, but also wrap this output in an <a> tag in certain cases, then you could use an idiom like
<xsl:template match="tag[#href]">
<xsl:call-template name="tagbody" />
</xsl:template>
<xsl:template match="tag" name="tagbody">
Tag content was "<xsl:value-of select="."/>"
</xsl:template>
The idea here is that tag elements with an href will match the first template, which does some additional processing before and after calling the general tag template. Tags without an href will just hit the normal template without the wrapping logic. I.e. for an input like
<root>
<tag>foo</tag>
<tag href="#">bar</tag>
</root>
you would get an output like
Tag content was "foo"
Tag content was "bar"
I had the same problem before and was only able to solve it by copying the entire <a href='{$href}'>...</a> for each when branch.
Maybe you could try setting the doctype of your XSL to some loose XML standard, but afaik XSLT is pretty strict.
Edit: apparently you can set the doctype with a <xsl:output> tag.
Found solution on the net:
<xsl:text disable-output-escaping="yes"><![CDATA[<a href=']]></xsl:text>
<xsl:value-of select="href"/>
<xsl:text disable-output-escaping="yes"><![CDATA['>]]></xsl:text>
I know this questions might seem a little odd, but I want to make sure.
One of my superiors is kind of convinced that there is a more or less easy way to convert the XML serialization of an object back to the java code that created it. I am, however, pretty sure that the best I can get is the object.
So basically my questions is: Is there any way to convert something like this
<java version="1.6.0_10" class="java.beans.XMLDecoder">
<object class="javax.swing.JPanel">
<void property="size">
<object class="java.awt.Dimension">
<int>42</int>
<int>23</int>
</object>
</void>
</object>
</java>
back to something like
JPanel jPanel = new JPanel();
jPanel.setSize(42,23);
Thanks in advance.
Provided that all serialized objects comply to the java beans contract, you can re-create the process that the XML de-serializer follows to unmarshal the java objects, in order to recreate the code that goes with it.
Back in the golden XML days, I worked some projects that used similar processes to generate Java code from XML definitions.
Departing from your serialized model, you can use a XSL-T transformation to recreate the code that lead to the serialized objects. This process will create very linear code (as in non-modular), but you'll have what you're looking for.
An example to get you started: To process the XML you provided, you can use the following recursive transformation: copy/paste it & try it here: online XSL-T (the template is based on Xpath 1.0 to be able to use the online tool. Xpath 2.0 will improve the code in some areas, like string functions)
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xf="http://www.w3.org/2005/xpath-functions">
<xsl:template match="object">
<xsl:call-template name="objectClass" /> <xsl:value-of select="string(' ')" />
<xsl:call-template name="objectNodeName" />
= new <xsl:call-template name="objectClass" />(<xsl:call-template name="objectParams" />);
<xsl:for-each select="*[#property]">
<xsl:apply-templates />
<xsl:call-template name="setProperty" />
</xsl:for-each>
</xsl:template>
<xsl:template match="/" >
<xsl:apply-templates match="/object" />
</xsl:template>
<xsl:template match="text()" />
<xsl:template name="objectNodeName">
<xsl:param name="node" select="." />
<xsl:value-of select="translate($node/#class,'.','_')" />_<xsl:value-of select="count($node/ancestor-or-self::*)" />
</xsl:template>
<xsl:template name="setProperty">
<xsl:call-template name="objectNodeName" > <xsl:with-param name="node" select="parent::node()"/></xsl:call-template>
.set<xsl:call-template name="capitalize"><xsl:with-param name="str" select="#property"/></xsl:call-template>(<xsl:call-template name="objectNodeName" > <xsl:with-param name="node" select="node()"/></xsl:call-template>);
</xsl:template>
<xsl:template name="objectClass">
<xsl:param name="fqn" select="#class" />
<xsl:value-of select="$fqn" />
</xsl:template>
<xsl:template name="objectParams">
<xsl:for-each select="*[not(child::object)]">
<xsl:if test="position() > 1">,</xsl:if><xsl:value-of select="." />
</xsl:for-each>
</xsl:template>
<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<xsl:template name="capitalize">
<xsl:param name="str" select="." />
<xsl:value-of select="concat(translate(substring($str,1,1),$smallcase,$uppercase),substring($str,2))">
</xsl:template>
</xsl:stylesheet>
Disclaimer: I tested the template on the sample provided and some variations of it, including some containign several more objects. I did not test deeper object nesting. It's an example and not a fully-functional XML Serialization to Java transformation, which is left as an exercise to the reader :-)
Yes, I think there are several ways to implement this. First of all you can use JAXB technology, read about it http://www.oracle.com/technetwork/articles/javase/index-140168.html#xmp1.
Second way: you always can read xml in runtime (DOM, SAX) and create objects dynamically using reflection.
I don't think this is possible because if object class can be everything, how would you know what method to call to set size x to 42? Maybe there is a setter for this, maybe just a constructor or the number was calculated somehow.
The only possibility I can imagine is through the use of reflection, that's more or less the same frameworks like XStream do. So you can create the same object, but not the same code that was originally used to create it.
It is not that difficult. I am not sure how this would work with Swing class like JPanel, but since it is a Java bean, it should not be a problem to use some kind of XML library like XStream, which is one of the easiest way of how to do such things. Or you could use more verbose JAXB or XML Beans.
Edit: I'm sorry I didn't notice that there already is an XMLDecoder mentioned, and there seems to be an article on how to 'read JavaBean from XML file using XMLDecoder'.
I suspect that the superiors belief was poorly articulated and/or poorly understood. In particular, "the XML serialization of an object" may have been meant to refer to the schema, not the XML for a particular object, so that "convert the XML serialization of an object back to the java code that created it" would mean going from schema to marshalling code - JAXB's XJC, or similar.
I have never seen any sort of generalized technology that can reliably reconstruct the actual code instructions used to create an object based on a general XML serialization. What you have is stuff like JAXB, XStream or xmlbeans that can recreate an object based on XML serialized information. This is pretty evident when you think about it since there can be any number of ways to code an object to a specific state. Just knowing the state (which is really what the XML serialization is - the object's state at a certain point in time) is not enough to deduce HOW the object got to that state.
Also, there are many types of information that is transient in nature and not serializable (thread handles, sockets, window handles, device context etc etc etc) so serialization is not applicable to all objects/classes to begin with.
I have a simply XSLT 1.0 stylesheet, that turns XML documents in XHTML. I really want to be able to "include" the content of an XML file in another when needed. AFAIK it is simply not possible in XSLT 1.0, so I decided to move my processing to a simple Java app that would pre-process the XML, executing the "includes" recursively, and passing it to the default JDK XSLT processor. I have a XML schema that my documents must conform to.
The most used element is called "text", and can have an "id" and/or a "class" attribute, which gets used for XHTML styling with CSS. This element gets turned into "p", "div", or "span" depending on the context.
What I would like to add, is the ability to define "unknown" elements in my input files, and have them transformed in a "text" element for further processing. If the "unknown" element's name start with a capital letter, then it becomes a "text", with "id" set to original name. Otherwise a "text" with "class" set to original name. Everything else in the unknown element should be kept as-is, and then it should be processed by XSLT as if it was originally in the input file. In other words, I would like to transform all unknown elements to for a valid XML document, and then process it with my stylesheet.
Can this be done in XSLT, possibly in a pre-processing "stylesheet", or should I do that as pre-processing in Java? Performance here is not important. I would prefer a XSLT solution, but not if it's much more complicated then doing it in Java.
Well, since no one answered, I just tried it. While is is easier to do it in Java, it has one major drawback: since the code need to know the valid elements so that it recognize the unknown ones, you end up having to hardcode that in your code and have to recompile it if the XSLT template changes.
So, I tried in XSLT and it also works. Let's say you have:
<xsl:template match="text">
*processing*
<xsl:call-template name="id_and_class"/>
*processing*
</xsl:template>
where the template named id_and_class copies your id and classes attribute in the generated element, and you want unknown elements to be mapped to "text" elements, then you can do this:
<xsl:template match="text">
<xsl:call-template name="text_processing"/>
</xsl:template>
<xsl:template name="text_processing">
*processing*
<xsl:call-template name="text_id_and_class"/>
*processing*
</xsl:template>
...
<xsl:template name="text_id_and_class">
<xsl:choose>
<!-- If name() is not "text", then we have an unknown element. -->
<xsl:when test="name()!='text'">
<!-- Processing of ID and class omitted ... -->
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="id_and_class"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
...
<!-- MUST BE LAST : Process unknown elements like a "text" element. -->
<xsl:template match="*">
<xsl:call-template name="text_processing"/>
</xsl:template>
If yon process the content of one specific element with a named template, then you can check in that template if the name matches, and use that for your special processing. Then you just have to put a <xsl:template match="*"> at the end of your stylesheet and call the named template from there.
I have a huge set of data and want to display the data with some formatting.
This is what the method basically looks like:
#ManagedOperation(description = "return html")
#ManagedOperationParameters({#ManagedOperationParameter(name = "someVal", description = "text")})
public String returnAsHtml(String someVal)
{
return "some formatted xml";
}
Looks like XSLTProcessor can be configured to use a XSLT template. However I could not find any examples on the internet using XSLT for html transformation in the context of MX4J. Could any one provide a sample XSLT template?
In case anyone comes back to this question, two things come to mind:
1) MX4J has several default implementations of HttpCommandProcessorAdaptor. These operations are mapped from the path. For JMX operations (aka ManagedOperation in Spring parlance), MX4J uses URLs like /invoke?operation=returnAsHtml
This will be passed to the InvokeOperationCommandProcessor to create an XML document with the result being just the toString() of whatever you returned, in an attribute called 'return'. It also passes back the return type in an attribute called 'returnclass'. You can see all this if you just add &template=identity to the invoke URL.
I mention all this because one option is to implement your own 'invoke.xsl'. The one in MX4J just calls the renderobject template:
Lo and behold, you find this in mbean_attributes.xsl, with a comment showing you exactly what you need to do:
<xsl:template name="renderobject">
<xsl:param name="objectclass"/>
<xsl:param name="objectvalue"/>
<xsl:choose>
<xsl:when test="$objectclass='javax.management.ObjectName'">
<xsl:variable name="name_encoded">
<xsl:call-template name="uri-encode">
<xsl:with-param name="uri">
<xsl:value-of select="$objectvalue"/>
</xsl:with-param>
</xsl:call-template>
</xsl:variable>
<a href="/mbean?objectname={$name_encoded}">
<xsl:value-of select="$objectvalue"/>
</a>
</xsl:when>
<xsl:otherwise>
<!-- Use the following line when the result of an invocation
returns e.g. HTML or XML data
<xsl:value-of select="$objectvalue" disable-output-escaping="true" />
-->
<xsl:value-of select="$objectvalue"/>
</xsl:otherwise>
</xsl:choose>
Setting 'disable-output-escaping' to true will do the trick
2) Another option is to write your own HttpCommandProcessorAdaptor, and set it on the HttpAdapter. This could either replace the 'invoke' processor, or you could have an entirely new one.
Hope that helps
One way I figured out is to use java script in the XSL template to extract and parse the string. Make sure you test for the browser (IE vs Non IE) and use proper parser.