【问题标题】:Setting text content in object generated by XSD在 XSD 生成的对象中设置文本内容
【发布时间】:2019-07-26 09:57:13
【问题描述】:

我有一个已转换为 .xsd 文件的 .dtd 文件。这个文件有一个元素Identity:

  <xs:element name="Identity">
    <xs:complexType mixed="true">
      <xs:sequence>
        <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##any" />
      </xs:sequence>
      <xs:attribute name="lastChangedTimestamp" type="xs:string" />
    </xs:complexType>
  </xs:element>

这会生成以下示例 xml,其中包含一些文本内容:

<Identity lastChangedTimestamp="lastChangedTimestamp1" xmlns="http://tempuri.org/cXML">text</Identity>

我使用 xsd.exe 将 .xsd 转换为 .cs 文件:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://tempuri.org/cXML")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://tempuri.org/cXML", IsNullable = false)]
public partial class Identity
{
    public string Text { get; set; }
    private System.Xml.XmlNode[] anyField;

    private string lastChangedTimestampField;

    /// <remarks/>
    [System.Xml.Serialization.XmlTextAttribute()]
    [System.Xml.Serialization.XmlAnyElementAttribute()]
    public System.Xml.XmlNode[] Any
    {
        get
        {
            return this.anyField;
        }
        set
        {
            this.anyField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string lastChangedTimestamp
    {
        get
        {
            return this.lastChangedTimestampField;
        }
        set
        {
            this.lastChangedTimestampField = value;
        }
    }
}

但是这不允许我设置身份节点的文本内容:

var credential = new Credential()
{
    Identity = new Identity()
    {
        lastChangedTimestamp = "lastChangedTimestamp1",
        //Text = "MyRef" <- would like to set it at this point
    }
};

我可以做些什么来确保当我序列化 Identity 对象时,我可以将我的 ref 放入节点的文本内容中,还是不支持?

<Identity lastChangedTimestamp="lastChangedTimestamp1">
    MyRef
</Identity>

【问题讨论】:

  • 我可以假设您手动添加了public string Text { get; set; } 吗?
  • “文本”是我认为可以设置的属性,但在自动生成的代码中不存在。我想避免更改系统生成的代码

标签: c# xml xsd dtd


【解决方案1】:

XSD 中的mixed="true" 表示&lt;Identity&gt; 元素可以包含mixed content

当该类型的元素可能包含字符数据时,该元素类型具有混合内容,可选地穿插child 元素。

此外,子元素不受 XSD 的约束。

xsd.exeXmlSerializer 通过 [XmlText][XmlAnyElement] 属性的组合支持混合内容。当这两个属性都应用于XmlNode[] 类型的成员时,XML 中包含的所有混合内容都将绑定到该成员。

在这种情况下,您会注意到 xsd.exe 已创建具有这些属性的 public System.Xml.XmlNode[] Any 成员,因此,要将文本“MyRef”添加到您的 XML,您需要将适当的 XmlText 添加到此数组:

var identity = new Identity()
{
    lastChangedTimestamp = "lastChangedTimestamp1",
    Any = new XmlNode []
    {
        new XmlDocument().CreateTextNode("MyRef"),
    },
};

演示小提琴here.

或者,您可以手动将Any 属性更改为对象数组,如this answer 中所示Sruly XmlSerializer - node containing text + xml + text

[XmlText(typeof(string))]
[XmlAnyElement]
public object[] Any { get; set; }

然后你就可以直接将字符串添加到数组中:

var identity = new Identity()
{
    lastChangedTimestamp = "lastChangedTimestamp1",
    Any = new object []
    {
        "MyRef",
    },
};

(您仍然需要为更复杂的 XML 分配 XmlNode 对象。)

演示小提琴#2 here.

【讨论】:

  • 效果很好,谢谢。我没有太多使用 XML,所以创建一个 XML 文档来存储一个字符串是非常违反直觉的,但这就是这样做的方法
【解决方案2】:

最后我更新了xsd Identity节点添加&lt;xs:extension base="xs:string"&gt;

  <xs:element name="Identity">
    <xs:complexType mixed="true">
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="lastChangedTimestamp" type="xs:string" />
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>

这在我的对象中创建了一个文本数组

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://tempuri.org/cXML")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://tempuri.org/cXML", IsNullable = false)]
    public partial class Identity
    {

        private string lastChangedTimestampField;

        private string[] textField;

        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string lastChangedTimestamp
        {
            get
            {
                return this.lastChangedTimestampField;
            }
            set
            {
                this.lastChangedTimestampField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlTextAttribute()]
        public string[] Text
        {
            get
            {
                return this.textField;
            }
            set
            {
                this.textField = value;
            }
        }
    }

然后我可以用它来设置我的参考:

new Credential()
{
    Identity = new Identity()
    {
        Text=new string[]
        {
            "MyRef"
        }
    }
}

不确定这是否是最好的方法,但我现在可以使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    • 2013-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    相关资源
    最近更新 更多