我可以重新排序现有的 XML 以遵守 XSD

Can I re-order an existing XML to adhere to an XSD(我可以重新排序现有的 XML 以遵守 XSD)

本文介绍了我可以重新排序现有的 XML 以遵守 XSD的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用 Java (org.w3c.dom.Node) 生成 XML,本质上使用

We're generating an XML with Java (org.w3c.dom.Node), using essentially

parent.appendChild(doc.createElement(nodeName));

这会生成一个 XML,其中节点按调用appendChild"的顺序排序.然而,最终的 XML 需要遵守给定的 XSD.我们的代码可以确保有效的值类型、必填字段等都可以.然而,我正在为节点顺序而苦苦挣扎.

this generates an XML where nodes are sorted by the order of calling the 'appendChild'. The final XML, however, needs to adhere to a given XSD. Our code can ensure that valid value types, mandatory fields etc. are ok. I am however struggling with the node order.

有没有办法:

  • 在插入时确保节点顺序与 XSD 匹配
  • 创建后根据 XSD 对整个 XML 重新排序

澄清一下:

我们拥有的是:

<myNodeA>...</myNodeA>
<myNodeC>...</myNodeC>
<myNodeB>...</myNodeB>

XSD 想要的是:

<myNodeA>...</myNodeA>
<myNodeB>...</myNodeB>
<myNodeC>...</myNodeC>

谢谢,西蒙

推荐答案

我之前通过遍历模式然后从 XML 模型中提取相关部分并沿途流式传输来完成此操作.

I've done this before by traversing the schema and then pulling relevant pieces from the XML model and streaming it along the way.

有多个 xsd 模型库可供使用:

There are multiple xsd model libraries to use:

  • xsom
  • 练习
  • xml架构

这是一个使用 xsom(可以替换为上述之一)和 xom(可以替换为 dom)的示例

Here's an example using xsom (which can be replaced by one of the above) and xom (which can be replaced with 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.

The actual reordering logic. You will probably have to modify this further. For example, I didn't have to deal with the xsd:any for my project.

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();
  }
}

这篇关于我可以重新排序现有的 XML 以遵守 XSD的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:我可以重新排序现有的 XML 以遵守 XSD

基础教程推荐