2012-07-16 51 views
0

我有以下XML文件:联合收割机XML和XSD文件

<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38"> 
<my:Text1></my:Text1> 
<my:Group> 
    <my:Text2></my:Text2> 
</my:Group> 
</my:myFields> 

和XSD定义它:

<xsd:schema targetNamespace="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<xsd:element name="myFields"> 
    <xsd:complexType> 
    <xsd:sequence> 
    <xsd:element ref="my:Text1" minOccurs="0"/> 
    <xsd:element ref="my:Group" minOccurs="0" maxOccurs="unbounded" /> 
    </xsd:sequence> 
    <xsd:anyAttribute processContents="lax" namespace="http://www.w3.org/XML/1998/namespace"/> 
    </xsd:complexType> 
</xsd:element> 
<xsd:element name="Text1" type="xsd:string"/> 
<xsd:element name="Group"> 
    <xsd:complexType> 
    <xsd:sequence> 
    <xsd:element ref="my:Text2" minOccurs="0"/> 
    </xsd:sequence> 
    </xsd:complexType> 
    <xsd:element name="Text2" type="xsd:string"/> 
</xsd:element> 
</xsd:schema> 

我想创建它是基于XML和XSD下面的XML文件:

<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38"> 
<my:Text1 type="string" minOccurs="0"></my:Text1> 
<my:Group minOccurs="0" maxOccurs="unbounded"> 
    <my:Text2 type="string" minOccurs="0"></my:Text2> 
</my:Group> 
</my:myFields> 

用.NET平台做这件事最简单的方法是什么?是否可以使用XSLT转换?

+0

是的,如果您将模式作为文档传递() – Woody 2012-07-16 11:40:02

+0

,则可以使用XSLT转换。不幸的是,我对XSLT转换不是很熟悉。如果可能,你能提供一个XSLT的例子吗? – Egor4eg 2012-07-16 11:41:56

+0

在接下来的一个小时内,我确信有人会在同一时间,但如果不是当我回来时,我会! – Woody 2012-07-16 11:50:07

回答

2

鉴于

<xsd:schema targetNamespace="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <xsd:element name="myFields"> 
     <xsd:complexType> 
      <xsd:sequence> 
       <xsd:element ref="my:Text1" minOccurs="0"/> 
       <xsd:element ref="my:Group" minOccurs="0" maxOccurs="unbounded" /> 
      </xsd:sequence> 
      <xsd:anyAttribute processContents="lax" namespace="http://www.w3.org/XML/1998/namespace"/> 
     </xsd:complexType> 
    </xsd:element> 
    <xsd:element name="Text1" type="xsd:string"/> 
    <xsd:element name="Text2" type="xsd:string"/> 
    <xsd:element name="Group"> 
     <xsd:complexType> 
      <xsd:sequence> 
       <xsd:element ref="my:Text2" minOccurs="0"/> 
      </xsd:sequence> 
     </xsd:complexType> 
    </xsd:element> 
</xsd:schema> 

校正模式和您指定的XML输入,这个样式表

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ext="http://exslt.org/common" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38"> 
<xsl:output method="xml" indent="yes"/> 
    <xsl:variable name="schema" select="document('so.xsd')//xsd:schema"/> 

<xsl:template match="/"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="my:*"> 
    <xsl:variable name="name" select="name()"></xsl:variable> 
    <xsl:variable name="basename" select="substring-after($name,':')"></xsl:variable> 
    <xsl:copy> 
     <xsl:variable name="types" select="$schema//xsd:element[@name=$basename]/@type"/> 
     <xsl:if test="$types"> 
      <xsl:attribute name="type"> 
       <xsl:value-of select="$types"/> 
      </xsl:attribute> 
     </xsl:if> 
     <xsl:for-each select="$schema//xsd:element[@ref=$name]/@*[name()!='ref']"> 
      <xsl:attribute name="{name()}"> 
       <xsl:value-of select="."/> 
      </xsl:attribute> 
     </xsl:for-each> 
     <xsl:apply-templates select="*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="node()|@*"> 
    <xsl:copy><xsl:apply-templates select="node()|@*" /></xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

产生下面的输出,我相信这是你想要的。

<?xml version="1.0" encoding="utf-8"?> 
<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003"> 
    <my:Text1 type="xsd:string" minOccurs="0"/> 
    <my:Group minOccurs="0" maxOccurs="unbounded"> 
     <my:Text2 type="xsd:string" minOccurs="0"/> 
    </my:Group> 
</my:myFields> 

它能做什么是加载架构作为一个文档,然后为每个元素,查找文件为该类型的元素,复制就可以了属性,然后寻找合适类型的ref和也复制这些元素。

唯一的问题是,它并不真正沿着模式旅行寻找正确的部分,它只是通过名称来解决它们。对于小型模式,可能大部分时间都是正确的,但偶尔也会导致问题。但是,对于你目前所展示的内容,它将起作用,并且它是一个可以从

+0

此解决方案仅适用于非常有限的一类模式。事实上,我怀疑它适用于与示例显着不同的任何架构。 – 2012-07-16 14:11:26

+0

是的,我说过它适用于一类有限的模式,但是假设它是一个有限的模式,您坚持使用xslt 1.0,我没有太多时间去查看,这是一个例子 – Woody 2012-07-16 14:36:52

+0

@Woody感谢这个例子。它完全符合我的要求。 – Egor4eg 2012-07-20 13:28:17

2

开始的地方。此XSLT 2.0样式表将探索您的模式插入适当的属性值minOccurs,maxOccurs类型。由于它基于模块化,因此可以轻松扩展其他可能包含的xsd属性。为了便于演示,我在样式表中插入了架构。虽然在实践中,你可能会把它留在外部。所以按照。

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:fn="http://www.w3.org/2005/xpath-functions" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" 
    xmlns:l="http://stackoverflow.com/questions/11502608" 
    exclude-result-prefixes="xsl xs fn xsd l"> 
<xsl:output indent="yes"/> 

<xsd:schema targetNamespace="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" 

... etc .. INSERT SCHEMA HERE !!! 

</xsd:schema> 


<xsl:template match="@*|node()"> 
<xsl:copy> 
    <xsl:apply-templates select="@*|node()" /> 
</xsl:copy> 
</xsl:template> 

<xsl:function name="l:xsd-attrib" as="attribute()?"> 
<xsl:param name="ele-name" as="xs:string"/> 
<xsl:param name="attri-name" as="xs:string"/> 
<xsl:sequence select="document('')/xsl:stylesheet/xsd:schema 
    //(xsd:element[ (substring-after(@ref,'my:')=$ele-name) or (@name=$ele-name)] 
    /@*[local-name(self::attribute())=$attri-name])" /> 
</xsl:function> 

<xsl:template name="l:emit-xsd-attri"> 
<xsl:param name="my-node" as="element()" /> 
<xsl:param name="attri-name" as="xs:string" /> 
    <xsl:variable name="ele" select="local-name($my-node)" /> 
    <xsl:if test="l:xsd-attrib($ele, $attri-name)"> 
    <xsl:attribute name="{$attri-name}"><xsl:value-of select=" 
    for $l in l:xsd-attrib($ele, $attri-name) return 
     if (contains($l, ':')) then substring-after($l, ':') else $l" /> 
    </xsl:attribute> 
    </xsl:if> 
</xsl:template> 

<xsl:template match="my:*"> 
<xsl:copy> 
    <xsl:apply-templates select="@*" /> 

    <xsl:call-template name="l:emit-xsd-attri"> 
    <xsl:with-param name="my-node" select="." /> 
    <xsl:with-param name="attri-name" select="'minOccurs'" /> 
    </xsl:call-template> 

    <xsl:call-template name="l:emit-xsd-attri"> 
    <xsl:with-param name="my-node" select="." /> 
    <xsl:with-param name="attri-name" select="'maxOccurs'" /> 
    </xsl:call-template> 

    <xsl:call-template name="l:emit-xsd-attri"> 
    <xsl:with-param name="my-node" select="." /> 
    <xsl:with-param name="attri-name" select="'type'" /> 
    </xsl:call-template> 

    <xsl:apply-templates select="node()" /> 
</xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
0

当您验证XML实例文档对抗模式,其结果是PSVI(架构验证后实例),其中包含所有你需要的信息,等等。唯一的问题是,如何在实践中掌握这些信息。这取决于你想使用的工具。例如,如果您使用Xerces作为您的模式验证程序,则有一个API可用于公开由模式处理器添加到实例的PSVI注释。