2012-05-10 51 views
8

我正在試驗用LinqToXSD創建XML數據綁定類,以及一個包含多個導入模式的XML模式。所有的模式都是located here.如何讓LinqToXSD正確輸出名稱空間前綴聲明?

要做到這一點,我用下面的根模式文檔:

<?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產生預期的輸出?

+0

謝謝! - 如果你確信模式不可能改變,他們可以註釋'Tmats.cs'文件中的所有元素來協助序列化程序,但是我個人只是將它轉換爲樣式表,然後離開它是。 –

回答

1

您應該映射每個導入的模式中:

<?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 =「不合格」。同樣,如果你希望暴露命名空間的每個架構必須指定將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> 

突出的問題是標籤的重複 - 一切看起來都對我好,仍然努力去理解爲什麼會發生這種情況。

UPDATE星期一:

我認爲這是在LinqToXSD工具的錯誤 - 我已經通過每一個組合我能想到的,不能始終如一地解決你的問題跑,但是...我設法解決<Tmats>重複問題:

在你XmlHelper文件,更改return語句:

System.Xml.Linq.XDocument xd = System.Xml.Linq.XDocument.Parse(sb.ToString()); 
return xd.Root.FirstNode.ToString(); 

我知道這是一個黑客,但它修復了問題並且您的LoopbackTest已通過。

如果創建使用Tmats類元素你沒有得到任何前綴,我試過和屬性的不同組合,我可以做的是重新連接的命名空間是最好的。如果你是與外部系統交換信息的話,我有一個修復

  1. 使用您的Tmats對象在你的代碼,
  2. 與命名空間序列化,通過XSLT映射
  3. 運行它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,你幾乎不會注意到它發生了什麼。

+0

我嘗試這樣做,它實際上沒有固定正由LinqToXSD生成的古怪底層C#命名空間('命名空間www.spiraltechinc.com.tmats.item106.item13.TmatsC'變得簡單地'TmatsC',例如),但保存的XML輸出沒有改變;它仍然在每個元素中都有xmlns聲明。 –

+0

我認爲這是與** [這](http://msdn.microsoft.com/en-us/library/bb387069.aspx)**,但我不知道如何將其納入LinqToXSD類。 –

+0

我得拍客工作 - 如果你能收拾好你的項目,並上傳到某個地方,我很高興在今天晚上晚些時候玩弄它爲你 - 這是一個有趣的問題。 –