XSD配置到引用属性在运行时在XML文件中配置

时间:2014-02-10 19:42:16

标签: java xml xsd

问题:是否有办法(类似tns:)为XML文件设置.xsd配置,以引用在其中配置的属性列表运行时的XML文件?

这是我的情况:

我有一个.xsd架构文件,Labels.xsd用于xml文件Labels.xml

Labels.xsd包含以下内容:

<complexType name="LabelList">
    <sequence>
        <element name="label" type="tns:MyLabel" maxOccurs="unbounded"
            minOccurs="1"/>
    </sequence>
</complexType>

<complexType name="MyLabel">
    <attribute name="labelName" type="token" use="required"/>
    <!-- There are other attributes and sequences in MyLabel -->
</complexType>

用户可以添加Labels.xml文件并添加自己的自定义标签,并在我的Java应用程序运行时更改名称。这些更改会在运行时获取。

我有另一个文件MyMainTable.xml,它使用Tables.xsd中的模式。此文件使用上面Labels.xml文件中的标签创建一个表。架构与Labels.xml文件的架构位于不同的架构文件中。

Tables.xml文件包含以下内容:

<complexType name="MyMainTable">
    <sequence>
        <element name="table" maxOccurs="unbounded">
            <complexType>
                <sequence>
                    <element name="tableElement" maxOccurs="unbounded">
                        <complexType>
                            <attribute name="name" type="string" use="required">
                                <annotation>
                                    <documentation>
                                    This should be one of the types of 
                                    MyLabel.label.labelName that are configured in the 
                                    LabelList sequence
                                    Users can change the names of and add to the 
                                    types in MyLabel.labelName xml file.
                                    </documentation>
                                </annotation>
                            </attribute>
                        </complexType>
                    </element>
                </sequence>
                <!-- There are other attributes in this type, but they are not relevant -->
             </complexType>
         </element>
     </sequence>
</complexType>

Labels.xml

的示例
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Labels xmlns="<my schema locaiton>">

<FavoriteLabels>
   <label labelName="LabelA">
     <!-- other attributes such as color -->
   </label>
   <label labelName="LabelB">
     <!-- other attributes such as color -->
   </label>
   <label labelName="LabelC">
     <!-- other attributes such as color -->
   </label>
</FavoriteLabels>

<OtherLabels>
   <label labelName="OtherA">
     <!-- other attributes such as color -->
   </label>
   <label labelName="OtherB">
     <!-- other attributes such as color -->
   </label>
   <label labelName="OtherC">
     <!-- other attributes such as color -->
   </label>
</OtherLabels>
</Labels>

tableElement中的名称可以在FavoriteLabels列表或OtherLabels列表中

目前我在构建表时检查了我的Java代码,但是我希望在解析XML文件时进行检查。与Enum文件中配置的.xsd的检查方式类似。

.xsd配置中是否有一种方法可以确保name的{​​{1}}属性包含在用户在{{1}运行时配置的标签列表中文件?

1 个答案:

答案 0 :(得分:1)

我在下面修改了你的例子。它可能会捕获您尝试解决的问题,或者至少向您展示可能的策略。

这是一个包含标签和表格的XML文件。

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://my-namespace my-schema.xsd"
      xmlns="http://my-namespace">
    <labels>
        <label label="LabelA"/>
        <label label="LabelB"/>
        <label label="LabelC"/>
    </labels>
    <tables>
        <table name="LabelB"/> 
        <table name="LabelB"/>
        <table name="LabelA"/> 
        <table name="LabelC"/>
    </tables>
</root>

您可能使用单独的文件(我无法仅使用XML Schema执行此操作,因为key / keyref关联使用XPath;但它可能是可行的,或者您可以在处理它们之前合并内存中的文件)。

在架构中,我定义了一个将标签与表相关联的键/ keyref对。这些关联是在定义它们的元素的上下文中使用XPath创建的。我使用ID和IDREF作为令牌类型,因为它们更严格,并保证整个文档的唯一性。

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
    xmlns:tns="http://my-namespace" targetNamespace="http://my-namespace">

    <xs:complexType name="LabelList">
        <xs:sequence>
            <xs:element name="label" maxOccurs="unbounded" minOccurs="1">
                <xs:complexType>
                    <xs:attribute name="label" type="xs:ID" use="required"/>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="TableList">
        <xs:sequence>
            <xs:element name="table" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:attribute name="name" type="xs:IDREF" use="required"/>                   
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:element name="root">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="labels" type="tns:LabelList"/>
                <xs:element name="tables" type="tns:TableList"/>
            </xs:sequence>
        </xs:complexType>

        <!-- These are the keys and references; they are in the current element's context -->
        <xs:key name="LabelsKey">
            <xs:selector xpath="labels/label"/>
            <xs:field xpath="@label"/>
        </xs:key>
        <xs:keyref name="TablesRef" refer="tns:LabelsKey">
            <xs:selector xpath="tables/table"/>
            <xs:field xpath="@name"/>
        </xs:keyref>

    </xs:element>
</xs:schema>

现在,如果添加一个未在列表中定义的标签表,例如:

<table name="LabelZ"/>

您将收到验证错误。