Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用模式按照模式对XML文档的元素重新排序_Java_Xml_Xsd_Xsom - Fatal编程技术网

Java 使用模式按照模式对XML文档的元素重新排序

Java 使用模式按照模式对XML文档的元素重新排序,java,xml,xsd,xsom,Java,Xml,Xsd,Xsom,假设我有一个XML文档(表示为文本、W3CDOM等),还有一个XML模式。XML文档具有模式定义的所有正确元素,但顺序错误 如何使用模式对文档中的元素“重新排序”,以符合模式定义的顺序 我知道这应该是可能的,可能是使用,因为JAXB XJC代码生成器使用元素的正确序列化顺序注释其生成的类 但是,我不熟悉XSOMAPI,而且它非常密集,所以我希望你们中的一位对此有一些经验,并能为我指明正确的方向。类似于“此父元素中允许哪些子元素,以及以什么顺序?” 让我举个例子 我有这样一个XML文档: <

假设我有一个XML文档(表示为文本、W3CDOM等),还有一个XML模式。XML文档具有模式定义的所有正确元素,但顺序错误

如何使用模式对文档中的元素“重新排序”,以符合模式定义的顺序

我知道这应该是可能的,可能是使用,因为JAXB XJC代码生成器使用元素的正确序列化顺序注释其生成的类

但是,我不熟悉XSOMAPI,而且它非常密集,所以我希望你们中的一位对此有一些经验,并能为我指明正确的方向。类似于“此父元素中允许哪些子元素,以及以什么顺序?”


让我举个例子

我有这样一个XML文档:

<A>
   <Y/>
   <X/>
</A>

我有一个XML模式,它说
的内容必须是
后跟
。现在很明显,如果我尝试根据模式验证文档,它会失败,因为
的顺序错误。但是我事先知道我的文档是“错误的”,所以我现在还没有使用模式进行验证。但是,我知道我的文档中包含了模式定义的所有正确元素,只是顺序不对

我想做的是以编程方式检查模式(可能使用XSOM,这是XML模式的对象模型),并询问它
的内容应该是什么。API将公开以下信息:“您需要一个
,后跟一个

因此,我获取我的XML文档(使用DOM API)并进行相应的重新排列,以便现在文档将根据模式进行验证

理解这里的XSOM很重要——它是一个java API,表示XML模式中包含的信息,而不是实例文档中包含的信息

我不想做的是从模式生成代码,因为模式在构建时是未知的。此外,XSLT没有任何用处,因为元素的正确顺序完全由模式中包含的数据字典决定


希望这已经足够明确了。

您的问题可以转化为:您有一个与模式不匹配的XSM文件,您希望将其转换为有效的文件

使用XSOM,您可以读取XSD中的结构,也许还可以分析XML,但它仍然需要从无效表单到有效表单的额外映射。样式表的使用会容易得多,因为您将遍历XML,使用XPath节点以正确的顺序处理元素。对于希望苹果优先于梨的XML,样式表将首先复制苹果节点(/Fruit/apple),然后再复制梨节点。这样,无论旧文件中的顺序如何,它们在新文件中的顺序都是正确的

使用XSOM可以读取XSD并生成样式表来重新排序数据。然后使用该样式表转换XML。一旦XSOM为XSD生成了一个样式表,您就可以重复使用该样式表,直到修改XSD或需要另一个XSD为止

当然,您可以使用XSOM以正确的顺序立即复制节点。但由于这意味着您的代码必须遍历所有节点和子节点,因此可能需要一些时间才能完成处理。样式表也可以做到这一点,但transformer将能够更快地处理它。它可以直接处理数据,而Java代码必须通过XMLDocument属性获取/设置每个节点。
因此,我将使用XSOM为XSD生成一个样式表,该样式表只需逐个节点复制XML节点即可反复使用。样式表只需要在XSD发生更改时重写,而且它的执行速度比Java API需要遍历节点本身时快。样式表不关心顺序,因此它总是以正确的顺序结束。
为了让它更有趣,您可以跳过XSOM,尝试使用读取XSD的样式表来生成另一个样式表。生成的样式表将按照样式表中定义的确切顺序复制XML节点。会很复杂吗?实际上,样式表需要为每个元素生成模板,并确保该元素中的子元素按正确的顺序处理

当我想到这一点时,我想知道以前是否已经这样做过。它将非常通用,能够处理几乎所有的XSD/XML


让我们看看。。。使用“//xsd:element/@name”可以获得模式中的所有元素名称。每个唯一的名称都需要翻译成模板。在这些模板中,您需要处理特定元素的子节点,这稍微复杂一些。元素可以有一个引用,您需要遵循该引用。否则,请获取所有子xsd:element节点。

对此我还没有一个好的答案,但我必须注意,这里可能存在歧义。考虑这个模式:

<xs:element name="root">
  <xs:choice>
    <xs:sequence>
      <xs:element name="foo"/>
      <xs:element name="bar">
        <xs:element name="dee">
        <xs:element name="dum">
      </xs:element>
    </xs:sequence>
    <xs:sequence>
      <xs:element name="bar">
        <xs:element name="dum">
        <xs:element name="dee">
      </xs:element>
      <xs:element name="foo"/>
    </xs:sequence>
  </xs:choice>
</xs:element>

这个输入XML:

<root>
  <foo/>
  <bar>
    <dum/>
    <dee/>
  </bar>
</root>


这可以通过重新排序
,或者通过重新排序
来符合模式。似乎没有任何理由选择一个而不是另一个。

基本上,您希望获取根元素,然后从那里递归地查看文档中的子元素和架构中定义的子元素,并使顺序匹配

我将为您提供一个C#语法解决方案,因为这是我日夜编写的代码,它非常接近Java。注意,我会
public void SortChildrenIntoNewDocument( XmlElement source, XmlElement target, SchemaElement schemaElement )
{
    // whatever method you use to ask the XSOM to tell you the correct contents
    SchemaElement[] orderedChildren = schemaElement.GetChildren();
    for( int i = 0; i < orderedChildren.Length; i++ )
    {
        XmlElement sourceChild = source.SelectChildByName( orderedChildren[ i ].Name );
        XmlElement targetChild = target.AddChild( sourceChild )
        // recursive-call
        SortChildrenIntoNewDocument( sourceChild, targetChild, orderedChildren[ i ] );
    }
}
public class JAXBSequenceUtil {
  public static void main(String[] args) throws JAXBException, IOException {

    String xml = FileUtils.readFileToString(new File(
            "./conf/out/Response_103_1015700001&^&IOF.xml"));

    System.out.println("Before marshalling : \n" + xml);
    String sequencedXml = correctSequence(xml,
            "org.acord.standards.life._2");
    System.out.println("After marshalling : \n" + sequencedXml);
  }

  /**
   * @param xml
   *            - XML string to be corrected for sequence.
   * @param jaxbPackage
   *            - package containing JAXB generated classes using XSD.
   * @return String - xml with corrected sequence
   * @throws JAXBException
   */
  public static String correctSequence(String xml, String jaxbPackage)
        throws JAXBException {
    JAXBContext jaxbContext = JAXBContext.newInstance(jaxbPackage);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
    Object txLifeType = unmarshaller.unmarshal(new InputSource(
            new StringReader(xml)));
    System.out.println(txLifeType);

    StringWriter stringWriter = new StringWriter();
    Marshaller marshaller = jaxbContext.createMarshaller();
    marshaller.marshal(txLifeType, stringWriter);

    return stringWriter.toString();
  }
}