支持XSD的XML到XML动态转换

支持XSD的XML到XML动态转换,xml,xsd,Xml,Xsd,我有一个输入XML,类似于: <Root> <FirstTag> <Attribute1>value1</Attribute1> <Attribute2>value2</Attribute2> <FirstTagValue>Test</FirstTagValue> </FirstTag> </Root> 价值1 价值2 试验 我想用java把它

我有一个输入XML,类似于:

<Root>
 <FirstTag>
    <Attribute1>value1</Attribute1>
    <Attribute2>value2</Attribute2>
    <FirstTagValue>Test</FirstTagValue>
 </FirstTag>
</Root>

价值1
价值2
试验
我想用java把它转换成

<ns:Root xmlns:ns="http://my.comp.com/root" xmlns:ns1="http://my.comp.com/child">
 <ns:FirstTag Attribute1="value1" Attribute2="value2">
    <ns1:FirstTagValue>Test</ns1:FirstTagValue>
 </ns:FirstTag>
</ns:Root>

试验

我为输出XML定义了一个XSD。因此,基本上我希望对照XSD检查输入XML标记,然后动态构建输出XML。

您可以使用XSD验证XML文档是否遵守其规则


XSD本身不会将一个XML文档转换为另一个XML文档。为此,请使用XSLT。

如果您想从模式中使用的唯一信息是决定是将子元素转换为属性,还是将其保留为子元素,那么您可以使用Saxon中的工具(您需要Saxon EE来了解模式)

首先,从您的模式创建一个SCM文件(使用
-scmout:schema.SCM
选项运行
com.saxonica.Validate
)。SCM文件是模式组件模型的XML表示,它比原始源模式更易于处理

在SCM文件中,对于类似
FirstTag
的元素,您会发现如下内容:

<scm:element id="C141"
                name="FirstTag"
                targetNamespace="http://something"
                type="C392".../>
<xsl:template match="*">
  <xsl:copy>
    <xsl:variable name="attributeChildren"
      select="*[f:elementHasAttribute(current()/local-name(), local-name())]"/>
    <xsl:for-each select="$attributeChildren">
      <xsl:attribute name="{local-name()}" select="."/>
    </xsl:for-each>
    <xsl:copy-of select="* except $attributeChildren"/>
  </xsl:copy>
</xsl:template>

然后您可以找到相应的类型:

<scm:complexType id="C392"
                    base="C344"
                    derivationMethod="extension"
                    abstract="false"
                    variety="mixed">
      <scm:attributeUse required="false" inheritable="false" ref="C1075"/>
      <scm:attributeUse required="false" inheritable="false" ref="C1076" default="no"/>
      <scm:attributeUse required="false" inheritable="false" ref="C1077"/>

对于每个属性,您会发现一个属性声明,如:

<scm:attribute id="C1075"
                  name="select"
                  type="C156".../>

因此,在XSLT中,您可以编写一个函数来测试给定元素是否具有这样的给定属性(忽略名称空间,并假设$SCM是保存SCM文档的全局变量):


现在您可以处理如下元素:

<scm:element id="C141"
                name="FirstTag"
                targetNamespace="http://something"
                type="C392".../>
<xsl:template match="*">
  <xsl:copy>
    <xsl:variable name="attributeChildren"
      select="*[f:elementHasAttribute(current()/local-name(), local-name())]"/>
    <xsl:for-each select="$attributeChildren">
      <xsl:attribute name="{local-name()}" select="."/>
    </xsl:for-each>
    <xsl:copy-of select="* except $attributeChildren"/>
  </xsl:copy>
</xsl:template>


我还没有测试过代码,但设计肯定会成功。

可能是我问的问题不正确。。我想使用java转换它,但不生成jaxb对象。。。如果我们可以在java中根据xsd验证xml,那么这应该是可能的。。我的意思是我需要一种方法来检查字段是xml标记还是属性。。类似java的东西,如果我能找到,那么我认为可以根据XSD定义构建输出xml。您可以在java中使用各种xml解析器库,但XSLT是将xml转换为xml的理想方法。