简体   繁体   中英

How to reorder node elements such that they match an xsd:sequence order?

Is there any way to reorder elements in a Node objects such that they match an xsd:sequence order? I've read through the docs for Node.normalize , but it doesn't seem to perform that function. Is there something else that can be done?

I believe that it can be done with XSLT, but it would sound like an overly convoluted solution to use XSLT, and a special java-xlst parser to perform the manipulation as opposed to having something native in java.

Or would I actually need to code a complex function to do the processing for me?

If I read your question correctly, what you want is rather a "magical" (as in a simple) way of getting nodes re-arranged according to an external XSD, as opposed to a way to move nodes around using some XML API.

If true, then I am not aware of any API that provides a generic way to achieve such a thing. It is also not a trivial piece of programming, given the complexity of the content models XSD is able to describe.

It is also, under very simple circumstances, virtually impossible to solve. Think of this very simple example: imagine a content model made up of two choices, i) sequence a - b - c , ii) sequence b - c - a. The XML content comes in the order c - b - a (as per your requirement, you want to take in invalid XML, and make it valid). In this example, which is the right way to do it?

Of course, I am not saying this is your scenario. I am simply trying to point out why no one, as far as I know, has come up with a solution to such a problem.

If your content model under the sequence is rather trivial, thus allowing for an unambiguous way of solving it irrespective of the sequence in which your XML arrives, or if the XML content comes in a known, but wrong way, all the time, then you have to code it using your preferred approach to XML manipulation - but I would suggest, don't try to make it generic, it is just going down the rabbit hole ;)....

If you only have xs:sequence to worry about, and not choice/repetition, and so long as the schema isn't written to use lots of complex features like named model groups and substitution groups and wildcards, then it shouldn't be too difficult, at any rate if you use XSLT 2.0 or XQuery and forget about trying to code it in Java. If the variable $seq is an xs:sequence element, then the sort key for an element named $E is "count($x/xs:element[(@name|@ref)=$E]/preceding-sibling::*", so you can just plug this expression into an xsl:sort as

<xsl:for-each select="*">
  <xsl:sort select="count($seq/xs:element[(@name|@ref)=local-name(current())]/preceding-sibling::*"/>
  ...
</xsl:for-each>

Probably needs a bit of finessing for namespaces or other things you might encounter, but you get the idea.

You can manipulate XML directly in Java using the following packages:

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;

You'll need to put an XML parser such as saxon ( see http://saxon.sourceforge.net/ ) on your classpath

You can manipulate the XML 'by hand', reading bits of the input document and creating the required output document or you can write an xslt style sheet and use it to transform the document straight from your Java code.

Try here for a starting point:

http://oreilly.com/catalog/javaxslt/chapter/ch05.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM