Java用于查询XSD文件的方法

5
我是一位有用的助手,可以为您翻译文本。
我有一组针对不同数据类型的xsd文件。在Java世界中,生成类型属性列表的最佳方法是什么?
例如,使用这两个文件。
文件:customer.xsd
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="customer">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="number" type="xs:integer"/>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="address" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
</xs:schema>

文件名: order.xsd

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="customer">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="orderid" type="xs:integer"/>
      <xs:element name="customer" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>
</xs:schema>

我想做两件事

1. 一个Java应用程序,读取XSD并进行处理(以某种方式?)。 因此,当您运行程序时,它可以将属性打印出来。

> java -jar printtypes.jar -f customer.xsd
> number : Integer
> name : String
> address : String

2. 一种生成新文件的转换方式
文件:customer.properties
<propertylist>
<prop>
 <name> orderid </name>
 <type> integer </type>
</prop>
<prop>
 <name> customer </name>
 <type> string</type>
</prop>
</propertylist>

我尝试使用Java反射来实现上述(1)中的程序,以查询由JAXB生成的Java类。这将创建一个类的实例并查询值和字段,但在值由空序列组成时无法正常工作。由于类型擦除,无法返回原始类型的值。最终会得到某些东西的空ArrayList,但您不知道是什么。我来自C++领域,目前对所有这些Java技术有点困惑。我的Google搜索失败了 - 我看到的大多数JAVA / XSD帖子都谈论验证,而这不是我想要做的事情。

2
实际上,你关于类型擦除导致类型丢失的说法是不正确的。类成员保留它们的泛型信息,因此您应该能够通过反射获取所需的所有内容。 - jtahlborn
准确地说,反射 API 可以完整地访问字段声明的类型。擦除只影响运行时类型的查询,即如果您有一个对象,则通常无法发现其类型参数。 - meriton
3个回答

2

问题 1. 可以使用 XPath 解决。例如,这个表达式:

/xs:schema/xs:element/xs:complexType/xs:sequence/xs:element/@name

将返回所有名称:

  • number(数字)
  • name(名称)
  • address(地址)

另请参阅:文档 - 如何通过名称获取标签的值?

对于问题2。 XSLT非常适合。以下是一个快速而简单的转换示例:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/xs:schema/xs:element/xs:complexType/xs:sequence">
<propertylist>
    <xsl:for-each select="xs:element">
    <prop>
        <name><xsl:value-of select="@name"/></name>
        <type><xsl:value-of select="@type"/></type>
    </prop>
    </xsl:for-each>
</propertylist>
</xsl:template>
</xsl:stylesheet>

应用于customer.xsd的结果如下:
<propertylist xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <prop>
        <name>number</name>
        <type>xs:integer</type>
    </prop>
    <prop>
        <name>name</name>
        <type>xs:string</type>
    </prop>
    <prop>
        <name>address</name>
        <type>xs:string</type>
    </prop>
</propertylist>

有趣的是,你在解决这两个问题时都不需要Java。

XPath表达式返回的是number类型还是name类型? - Cratylus
1
@user384706:为什么不试一下呢?在Linux上你可以使用命令行工具_xsltproc_和xmllint。 - extraneon
仔细看,如果您使用/xs:schema/xs:element/xs:complexType/xs:sequence/xs:element/@type,它将返回:[xs:integerxs:stringxs:string]。如果您只查询 /xs:schema/xs:element/xs:complexType/xs:sequence/xs:element,您将得到一个包含 3 个 xs:element 的列表,然后您可以针对每个元素子查询 @name@type - Tomasz Nurkiewicz
我强烈建议不要直接从XSD文档中工作。在XSD中有太多表达同一事物的方式,编写能正确处理XSD语言的代码非常困难。 - Michael Kay

2
你可能需要了解XSOM,它是一个项目,可以将你的XML模式导入并生成对象,你可以遍历这些对象并生成所需的结果。

http://xsom.java.net/userguide.html

手动解析模式可能非常棘手,因为有不同的方法可以表达基本相同的内容。

谢谢大家,我首先在解决问题1的工作中看了一下XSOM的方法。相比使用XPATH,它看起来更加强类型化。但是我对XSOM的细节有些困惑。我没有在这里发表评论,而是提出了一个新问题[链接](https://dev59.com/NFzUa4cB1Zd3GeqP57zj) - DUFF
该API需要一点时间来理解,但我认为它可能比使用XSLT更为稳健。虽然如果您需要快速、简单的解决方案,并且项目寿命有限,那么XSLT也不是一个坏选择。我没有听说过SCM,但如果它可以做同样的事情并且具有类似的API,那么也值得一看。 - BillRobertson42

1

如上所建议的,XSOM是一种方法。

另一种方法是Saxon的SCM。 Saxon模式处理器将读取一组模式文档,并在名为SCM的XML表示中输出相应的模式组件模型。然后,这比原始的XSD文档更容易处理。如果您想在Java中进行后续处理,则可能更有意义使用XSOM;如果您想在XSLT或XQuery中进行处理,则使用Saxon SCM更有意义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接