.net 组合XML和XSD文件
我有以下XML文件:.net 组合XML和XSD文件,.net,xml,xslt,xsd,.net,Xml,Xslt,Xsd,我有以下XML文件: <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>
<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转换吗 给出了一个正确的
<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并复制这些元素
唯一的问题是,它实际上并没有沿着模式向下移动以查找正确的部分,它只是按名称来处理它们。对于小型模式,可能大多数情况下都是正确的,但有时可能会导致问题。但对于您目前展示的内容,它将起作用,并且它是一个从给出正确的架构开始的地方
<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并复制这些元素
唯一的问题是,它实际上并没有沿着模式向下移动以查找正确的部分,它只是按名称来处理它们。对于小型模式,可能大多数情况下都是正确的,但有时可能会导致问题。但是对于您目前正在展示的内容,它将起作用,并且是一个从开始的地方。此XSLT 2.0样式表将探索您的模式,并为minOccurs、maxOccurs和type插入适当的属性值。由于它是基于模块的,因此很容易扩展到您可能希望包含的其他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>
此XSLT2.0样式表将探索您的模式,并为minOccurs、maxOccurs和type插入适当的属性值。由于它是基于模块的,因此很容易扩展到您可能希望包含的其他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>
当您根据模式验证XML实例文档时,结果是一个PSVI(模式验证后实例),其中包含您需要的所有信息,等等。唯一的问题是,如何在实践中掌握这些信息。这取决于您想要使用的工具。例如,如果您使用Xerces作为模式验证器,则会有一个API来公开模式处理器添加到实例中的PSVI注释。当您根据模式验证XML实例文档时,结果是一个PSVI(模式验证后实例),其中包含您需要的所有信息,等等。唯一的问题是,如何在实践中掌握这些信息。这取决于您想要使用的工具。例如,如果您使用Xerces作为模式验证器,则会有一个API来公开模式处理器添加到实例中的PSVI注释。是的,如果您将模式作为文档传入,则可以使用XSLT翻译()很遗憾,我对XSLT翻译不是很熟悉。如果可能的话,你能提供一个XSLT的例子吗?在接下来的一个小时里,我肯定会有人在这段时间内,但如果没有,当我回来的时候,我会的!你还没有申报我的:Text2。您的文档因您自己的架构无效。更正。您的架构是无效的。是的,如果您将架构作为文档传递进来,XSLT翻译是可能的()不幸的是,我对XSLT翻译不是很熟悉。如果可能的话,你能提供一个XSLT的例子吗?在接下来的一个小时里,我肯定会有人在这段时间内,但如果没有,当我回来的时候,我会的!你还没有申报我的:Text2。您的文档因您自己的架构无效。更正。您的架构无效。此解决方案仅适用于非常有限的一类架构。事实上,我怀疑它是否适用于与所示示例显著不同的任何模式。是的,我说过它适用于有限类别的模式,但在假设它是有限模式的限制条件下,您仍然坚持使用xslt 1.0,我没有太多时间去看,这是一个example@Woody谢谢你的例子。它完全符合我的要求。这个解决方案只适用于非常有限的一类模式。事实上,我怀疑它是否适用于与所示示例显著不同的任何模式。是的,我说过它适用于有限类别的模式,但在假设它是有限模式的限制条件下,您仍然坚持使用xslt 1.0,我没有太多时间去看,我