我正在尝试使用 LinqToXSD 创建 XML 数据绑定(bind)类和一个包含许多导入模式的 XML 模式。所有的模式都是 located here.
为此,我使用了以下根架构文档:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:TmatsG="http://www.spiraltechinc.com/tmats/106-13/TmatsG" elementFormDefault="unqualified">
<xs:import namespace="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon" schemaLocation="TmatsCommonTypes.xsd"/>
<xs:import namespace="http://www.spiraltechinc.com/tmats/106-13/TmatsC" schemaLocation="TmatsCGroup.xsd"/>
<xs:import namespace="http://www.spiraltechinc.com/tmats/106-13/TmatsD" schemaLocation="TmatsDGroup.xsd"/>
<xs:import namespace="http://www.spiraltechinc.com/tmats/106-13/TmatsG" schemaLocation="TmatsGGroup.xsd"/>
<xs:import namespace="http://www.spiraltechinc.com/tmats/106-13/TmatsH" schemaLocation="TmatsHGroup.xsd"/>
<xs:import namespace="http://www.spiraltechinc.com/tmats/106-13/TmatsM" schemaLocation="TmatsMGroup.xsd"/>
<xs:import namespace="http://www.spiraltechinc.com/tmats/106-13/TmatsP" schemaLocation="TmatsPGroup.xsd"/>
<xs:import namespace="http://www.spiraltechinc.com/tmats/106-13/TmatsR" schemaLocation="TmatsRGroup.xsd"/>
<xs:import namespace="http://www.spiraltechinc.com/tmats/106-13/TmatsS" schemaLocation="TmatsSGroup.xsd"/>
<xs:import namespace="http://www.spiraltechinc.com/tmats/106-13/TmatsT" schemaLocation="TmatsTGroup.xsd"/>
<xs:import namespace="http://www.spiraltechinc.com/tmats/106-13/TmatsV" schemaLocation="TmatsVGroup.xsd"/>
<xs:element name="Tmats" type="TmatsG:Tmats">
<xs:annotation>
<xs:documentation>Tmats Root</xs:documentation>
</xs:annotation>
</xs:element>
</xs:schema>
我使用 Linq to XSD 创建了类。然后我写了下面的测试:
[TestMethod()]
public void TmatsXmlExample4()
{
Tmats tmats = new Tmats
{
ProgramName = "My Program",
OriginationDate = DateTime.Now,
};
tmats.PointOfContact.Add(new PointOfContactType
{
Address = "12345 Anywhere Street",
Agency = "My Agency",
Name = "Robert Harvey",
Telephone = "111-222-3333"
});
Debug.Print(tmats.ToString());
}
我期望输出看起来像这样:
<Tmats>
<TmatsG:ProgramName>My Program</TmatsG:ProgramName>
<TmatsG:OriginationDate>2012-05-09-07:00</TmatsG:OriginationDate>
<TmatsG:PointOfContact>
<TmatsCommon:Name>Robert Harvey</TmatsCommon:Name>
<TmatsCommon:Agency>My Agency</TmatsCommon:Agency>
<TmatsCommon:Address>12345 Anywhere Street</TmatsCommon:Address>
<TmatsCommon:Telephone>111-222-3333</TmatsCommon:Telephone>
</TmatsG:PointOfContact>
</Tmats>
相反,我得到的是:
<Tmats>
<ProgramName xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsG">My Program</ProgramName>
<OriginationDate xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsG">2012-05-09-07:00</OriginationDate>
<PointOfContact xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsG">
<Name xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon">Robert Harvey</Name>
<Agency xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon">My Agency</Agency>
<Address xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon">12345 Anywhere Street</Address>
<Telephone xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon">111-222-3333</Telephone>
</PointOfContact>
</Tmats>
有没有办法让 LinqToXSD 产生预期的输出?
最佳答案
您应该映射每个导入的模式:
<?xml version="1.0"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:TmatsCommon="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon"
xmlns:TmatsC="http://www.spiraltechinc.com/tmats/106-13/TmatsC"
xmlns:TmatsD="http://www.spiraltechinc.com/tmats/106-13/TmatsD"
xmlns:TmatsG="http://www.spiraltechinc.com/tmats/106-13/TmatsG"
xmlns:TmatsH="http://www.spiraltechinc.com/tmats/106-13/TmatsH"
xmlns:TmatsM="http://www.spiraltechinc.com/tmats/106-13/TmatsM"
…
elementFormDefault="unqualified">
elementFormDefault 仅适用于它所在的模式,它不会覆盖任何包含或导入中的设置。
如果您想隐藏命名空间,那么所有模式都必须指定 elementFormDefault="unqualified"。同样,如果您想要公开命名空间,每个模式都必须指定 elementFormDefault= “合格”
更新在审查单元测试后:
您的输入:
<Tmats
xmlns:TmatsG="http://www.spiraltechinc.com/tmats/106-13/TmatsG"
xmlns:TmatsCommon="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon">
<TmatsG:ProgramName>My Project</TmatsG:ProgramName>
<TmatsG:OriginationDate>2012-05-15</TmatsG:OriginationDate>
你的输出:
<Tmats>
<Tmats
xmlns:TmatsG="http://www.spiraltechinc.com/tmats/106-13/TmatsG"
xmlns:TmatsCommon="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon">
<TmatsG:ProgramName>My Project</TmatsG:ProgramName>
<TmatsG:OriginationDate>2012-05-15</TmatsG:OriginationDate>
突出的问题是标签重复 - 我看起来一切正常,但仍在努力理解为什么会发生这种情况。
周一更新:
我认为 LinqToXSD 工具中存在错误 - 我已经遍历了所有我能想到的组合,但无法始终如一地解决您的问题,但是...我已设法修复 <Tmats>
重复问题:
在您的 XmlHelper 文件中,更改返回语句:
System.Xml.Linq.XDocument xd = System.Xml.Linq.XDocument.Parse(sb.ToString());
return xd.Root.FirstNode.ToString();
我知道这是一个hack,但它解决了问题并且您的 LoopbackTest 通过了。
如果您使用 Tmats 类创建元素,您不会获得任何前缀,我已经尝试了各种属性组合,我能做的最好的就是重新附加 namespace 。如果您要与外部系统交换信息,那么我有一个修复:
- 在您的代码中使用您的 Tmats 对象,
- 用命名空间序列化它,
- 通过 XSLT 运行它以将 ns 映射到前缀。
我知道它很笨重,但我认为这是您在实际修复 LinqToXSD 代码之前得到的最好结果。
XSLT 将命名空间映射到前缀(您需要在“样式表”声明和“映射器”中维护命名空间集:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:mapper="http://mapper"
xmlns:TmatsCommon="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon"
xmlns:TmatsC="http://www.spiraltechinc.com/tmats/106-13/TmatsC"
xmlns:TmatsD="http://www.spiraltechinc.com/tmats/106-13/TmatsD"
xmlns:TmatsG="http://www.spiraltechinc.com/tmats/106-13/TmatsG"
xmlns:TmatsH="http://www.spiraltechinc.com/tmats/106-13/TmatsH"
xmlns:TmatsM="http://www.spiraltechinc.com/tmats/106-13/TmatsM"
xmlns:TmatsP="http://www.spiraltechinc.com/tmats/106-13/TmatsP"
xmlns:TmatsR="http://www.spiraltechinc.com/tmats/106-13/TmatsR"
xmlns:TmatsS="http://www.spiraltechinc.com/tmats/106-13/TmatsS"
xmlns:TmatsT="http://www.spiraltechinc.com/tmats/106-13/TmatsT"
xmlns:TmatsV="http://www.spiraltechinc.com/tmats/106-13/TmatsV">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<mapper:namespaces>
<ns prefix="TmatsCommon" uri="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon"/>
<ns prefix="TmatsC" uri="http://www.spiraltechinc.com/tmats/106-13/TmatsC"/>
<ns prefix="TmatsD" uri="http://www.spiraltechinc.com/tmats/106-13/TmatsD"/>
<ns prefix="TmatsG" uri="http://www.spiraltechinc.com/tmats/106-13/TmatsG"/>
<ns prefix="TmatsH" uri="http://www.spiraltechinc.com/tmats/106-13/TmatsH"/>
<ns prefix="TmatsM" uri="http://www.spiraltechinc.com/tmats/106-13/TmatsM"/>
<ns prefix="TmatsP" uri="http://www.spiraltechinc.com/tmats/106-13/TmatsP"/>
<ns prefix="TmatsR" uri="http://www.spiraltechinc.com/tmats/106-13/TmatsR"/>
<ns prefix="TmatsS" uri="http://www.spiraltechinc.com/tmats/106-13/TmatsS"/>
<ns prefix="TmatsT" uri="http://www.spiraltechinc.com/tmats/106-13/TmatsT"/>
<ns prefix="TmatsV" uri="http://www.spiraltechinc.com/tmats/106-13/TmatsV"/>
</mapper:namespaces>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[namespace-uri()=document('')/*/mapper:namespaces/*/@uri]">
<xsl:variable name="vNS" select="document('')/*/mapper:namespaces/*[@uri=namespace-uri(current())]"/>
<xsl:element name="{$vNS/@prefix}:{local-name()}" namespace="{namespace-uri()}" >
<xsl:copy-of select="namespace::*[not(. = namespace-uri(current()))]"/>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
产生:
<Tmats>
<TmatsG:ProgramName xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsG">My Program</TmatsG:ProgramName>
<TmatsG:OriginationDate xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsG">2012-05-09-07:00</TmatsG:OriginationDate>
<TmatsG:PointOfContact xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsG">
<TmatsCommon:Name xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon">Robert Harvey</TmatsCommon:Name>
<TmatsCommon:Agency xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon">My Agency</TmatsCommon:Agency>
<TmatsCommon:Address xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon">12345 Anywhere Street</TmatsCommon:Address>
<TmatsCommon:Telephone xmlns="http://www.spiraltechinc.com/tmats/106-13/TmatsCommon">111-222-3333</TmatsCommon:Telephone>
</TmatsG:PointOfContact>
</Tmats>
好吧,这远非理想,但你的代码在项目内部运行良好,只有当你需要与其他人交互时,你需要修复 xml 输出(记住更改 elementFormDefault= “合格”(或将其删除)在您的 XSD 中)- 如果您将 XSLT 缓存为 XslCompiledTransform
您几乎不会注意到它的发生。
关于c# - 如何让 LinqToXSD 正确输出 namespace 前缀声明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10543583/