これは、スキーマをトラバースし、関連する部分を XML モデルから取り出し、途中でストリーミングするという方法で行ったことがあります。
使用する複数の xsd モデル ライブラリがあります。
xsom (上記のいずれかに置き換えることができます) と xom (dom に置き換えることができます) を使用した例を次に示します。
主要:
package main;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamWriter;
import node.xom.WrappedDocument;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Element;
import reorder.xsom.UncheckedXMLStreamWriter;
import reorder.xsom.XSVisitorWriteOrdered;
import com.sun.xml.xsom.XSElementDecl;
import com.sun.xml.xsom.XSSchemaSet;
import com.sun.xml.xsom.parser.XSOMParser;
public class ReorderXmlToXsd {
public static void main(String[] args) throws Exception {
File unorderedXml = new File("unordered.xml");
File xsd = new File("your.xsd");
File orderedXml = new File("ordered.xml");
XSOMParser p = new XSOMParser();
p.parse(xsd);
XSSchemaSet parsed = p.getResult();
Builder xom = new Builder();
Document unorderedDoc = xom.build(unorderedXml);
Element unorderedRoot = unorderedDoc.getRootElement();
XSElementDecl root = parsed.getElementDecl(
unorderedRoot.getNamespaceURI(),
unorderedRoot.getLocalName());
XMLOutputFactory stax = XMLOutputFactory.newInstance();
try (OutputStream to = new FileOutputStream(orderedXml)) {
XMLStreamWriter using = stax.createXMLStreamWriter(to, "UTF-8");
root.visit(
new XSVisitorWriteOrdered(
new WrappedDocument(unorderedDoc),
new UncheckedXMLStreamWriter(using)));
}
}
}
実際の並べ替えロジック。おそらくこれをさらに変更する必要があります。たとえば、私のプロジェクトでは xsd:any を扱う必要はありませんでした。
package reorder.xsom;
import node.WrappedNode;
import com.sun.xml.xsom.*;
import com.sun.xml.xsom.visitor.XSVisitor;
public class XSVisitorWriteOrdered implements XSVisitor {
private final WrappedNode currNode;
private final UncheckedXMLStreamWriter writeTo;
public XSVisitorWriteOrdered(WrappedNode currNode, UncheckedXMLStreamWriter writeTo) {
this.currNode = currNode;
this.writeTo = writeTo;
}
@Override
public void attributeUse(XSAttributeUse use) {
attributeDecl(use.getDecl());
}
@Override
public void modelGroupDecl(XSModelGroupDecl decl) {
modelGroup(decl.getModelGroup());
}
@Override
public void modelGroup(XSModelGroup model) {
for (XSParticle term : model.getChildren()) {
term.visit(this);
}
}
@Override
public void particle(XSParticle particle) {
XSTerm term = particle.getTerm();
term.visit(this);
}
@Override
public void complexType(XSComplexType complex) {
for (XSAttributeUse use : complex.getAttributeUses()) {
attributeUse(use);
}
XSContentType contentType = complex.getContentType();
contentType.visit(this);
}
@Override
public void elementDecl(XSElementDecl decl) {
String namespaceUri = decl.getTargetNamespace();
String localName = decl.getName();
for (WrappedNode child : currNode.getChildElements(namespaceUri, localName)) {
writeTo.writeStartElement(namespaceUri, localName);
XSType type = decl.getType();
type.visit(new XSVisitorWriteOrdered(child, writeTo));
writeTo.writeEndElement();
}
}
@Override
public void attributeDecl(XSAttributeDecl decl) {
String namespaceUri = decl.getTargetNamespace();
String localName = decl.getName();
WrappedNode attribute = currNode.getAttribute(namespaceUri, localName);
if (attribute != null) {
String value = attribute.getValue();
if (value != null) {
writeTo.writeAttribute(namespaceUri, localName, value);
}
}
}
@Override
public void simpleType(XSSimpleType simpleType) {
String value = currNode.getValue();
if (value != null) {
writeTo.writeCharacters(value);
}
}
@Override
public void empty(XSContentType empty) {}
@Override
public void facet(XSFacet facet) {}
@Override
public void annotation(XSAnnotation ann) {}
@Override
public void schema(XSSchema schema) {}
@Override
public void notation(XSNotation notation) {}
@Override
public void identityConstraint(XSIdentityConstraint decl) {}
@Override
public void xpath(XSXPath xp) {}
@Override
public void wildcard(XSWildcard wc) {}
@Override
public void attGroupDecl(XSAttGroupDecl decl) {}
}
スタックスライター:
package reorder.xsom;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
public class UncheckedXMLStreamWriter {
private final XMLStreamWriter real;
public UncheckedXMLStreamWriter(XMLStreamWriter delegate) {
this.real = delegate;
}
public void writeStartElement(String namespaceUri, String localName) {
try {
real.writeStartElement(namespaceUri, localName);
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
public void writeEndElement() {
try {
real.writeEndElement();
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
public void writeAttribute(String namespaceUri, String localName, String value) {
try {
real.writeAttribute(namespaceUri, localName, value);
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
public void writeCharacters(String value) {
try {
real.writeCharacters(value);
} catch (XMLStreamException e) {
throw new RuntimeException(e);
}
}
}
xml ビュー:
package node;
import java.util.List;
import javax.annotation.Nullable;
public interface WrappedNode {
List<? extends WrappedNode> getChildElements(String namespaceUri, String localName);
@Nullable
WrappedNode getAttribute(String namespaceUri, String localName);
@Nullable
String getValue();
}
XOM の実装:
書類:
package node.xom;
import java.util.Collections;
import java.util.List;
import node.WrappedNode;
import nu.xom.Document;
import nu.xom.Element;
public class WrappedDocument implements WrappedNode {
private final Document d;
public WrappedDocument(Document d) {
this.d = d;
}
@Override
public List<WrappedElement> getChildElements(String namespaceUri, String localName) {
Element root = d.getRootElement();
if (isAt(root, namespaceUri, localName)) {
return Collections.singletonList(new WrappedElement(root));
}
return Collections.emptyList();
}
@Override
public WrappedAttribute getAttribute(String namespaceUri, String localName) {
throw new UnsupportedOperationException();
}
@Override
public String getValue() {
throw new UnsupportedOperationException();
}
@Override
public String toString() {
return d.toString();
}
private static boolean isAt(Element e, String namespaceUri, String localName) {
return namespaceUri.equals(e.getNamespaceURI())
&& localName.equals(e.getLocalName());
}
}
エレメント:
package node.xom;
import java.util.AbstractList;
import java.util.List;
import node.WrappedNode;
import nu.xom.Attribute;
import nu.xom.Element;
import nu.xom.Elements;
class WrappedElement implements WrappedNode {
private final Element e;
WrappedElement(Element e) {
this.e = e;
}
@Override
public List<WrappedElement> getChildElements(String namespaceUri, String localName) {
return asList(e.getChildElements(localName, namespaceUri));
}
@Override
public WrappedAttribute getAttribute(String namespaceUri, String localName) {
Attribute attribute = e.getAttribute(localName, namespaceUri);
return (attribute != null) ? new WrappedAttribute(attribute) : null;
}
@Override
public String getValue() {
return e.getValue();
}
@Override
public String toString() {
return e.toString();
}
private static List<WrappedElement> asList(final Elements eles) {
return new AbstractList<WrappedElement>() {
@Override
public WrappedElement get(int index) {
return new WrappedElement(eles.get(index));
}
@Override
public int size() {
return eles.size();
}
};
}
}
属性:
package node.xom;
import java.util.List;
import node.WrappedNode;
import nu.xom.Attribute;
class WrappedAttribute implements WrappedNode {
private final Attribute a;
WrappedAttribute(Attribute a) {
this.a = a;
}
@Override
public List<WrappedNode> getChildElements(String namespaceUri, String localName) {
throw new UnsupportedOperationException();
}
@Override
public WrappedNode getAttribute(String namespaceUri, String localName) {
throw new UnsupportedOperationException();
}
@Override
public String getValue() {
return a.getValue();
}
@Override
public String toString() {
return a.toString();
}
}