2012-07-16 56 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註釋。