使用XmlAttributeOverrides更改对象树中的元素名称

时间:2013-12-16 17:15:00

标签: c# .net xml xml-serialization xml-attribute

我需要弄清楚如何使用从数据库中检索的值作为我的元素名称来重命名生成的XML中的元素和/或属性。

例如,这是我当前进程的潜在XML输出:

<ArrayOfEntityTreeBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <EntityTreeBase EntityInfo="User">
    <Children>
      <EntityTreeBase EntityInfo="User Medication">
        <Properties>
          <EntityProperty CreatedDate="2013-11-14T16:41:12.75">
            <FieldName>Medication Name</FieldName>
            <Value>Celebrex</Value>
          </EntityProperty>
          <EntityProperty CreatedDate="2013-12-04T14:08:58.597">
            <FieldName>Medication Dosage</FieldName>
            <Value>20000MG</Value>
          </EntityProperty>
          <EntityProperty CreatedDate="2013-11-14T16:41:12.76">
            <FieldName>Medication Prescribed Date</FieldName>
            <Value>08/01/2013</Value>
          </EntityProperty>
        </Properties>
      </EntityTreeBase>
      <EntityTreeBase EntityInfo="User Medication">
        <Properties>
          <EntityProperty CreatedDate="2013-11-14T16:41:12.767">
            <FieldName>Medication Name</FieldName>
            <Value>Aspirin</Value>
          </EntityProperty>
          <EntityProperty CreatedDate="2013-11-14T16:41:12.77">
            <FieldName>Medication Dosage</FieldName>
            <Value>5 mg</Value>
          </EntityProperty>
          <EntityProperty CreatedDate="2013-11-14T16:41:12.78">
            <FieldName>Medication Prescribed Date</FieldName>
            <Value>09/01/2013</Value>
          </EntityProperty>
        </Properties>
      </EntityTreeBase>
      <EntityTreeBase EntityInfo="User Medication">
        <Properties>
          <EntityProperty CreatedDate="2013-11-14T16:41:12.783">
            <FieldName>Medication Name</FieldName>
            <Value>Celebrex</Value>
          </EntityProperty>
          <EntityProperty CreatedDate="2013-11-14T16:41:12.793">
            <FieldName>Medication Dosage</FieldName>
            <Value>50 mg twice a day</Value>
          </EntityProperty>
          <EntityProperty CreatedDate="2013-11-14T16:41:12.8">
            <FieldName>Medication Prescribed Date</FieldName>
            <Value>10/01/2013</Value>
          </EntityProperty>
        </Properties>
      </EntityTreeBase>
    </Children>
    <Properties>
      <EntityProperty CreatedDate="2013-12-03T13:48:03.45">
        <FieldName>User First Name</FieldName>
        <Value>John</Value>
      </EntityProperty>
      <EntityProperty CreatedDate="2013-12-03T11:36:31.423">
        <FieldName>User MI</FieldName>
        <Value>Q</Value>
      </EntityProperty>
      <EntityProperty CreatedDate="2013-11-19T09:56:44.66">
        <FieldName>User Last Name</FieldName>
        <Value>Public</Value>
      </EntityProperty>
      <EntityProperty CreatedDate="2013-11-14T16:41:12.803">
        <FieldName>User SSN</FieldName>
        <Value>111-22-3333</Value>
      </EntityProperty>
    </Properties>
  </EntityTreeBase>
</ArrayOfEntityTreeBase>

我需要做的是:

<UserInformation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <User>
    <UserMedications>
      <UserMedication>
        <MedicationProperties>
          <MedicationProperty CreatedDate="2013-11-14T16:41:12.75">
            <FieldName>Medication Name</FieldName>
            <Value>Celebrex</Value>
          </MedicationProperty>
          <MedicationProperty CreatedDate="2013-12-04T14:08:58.597">
            <FieldName>Medication Dosage</FieldName>
            <Value>20000MG</Value>
          </MedicationProperty>
          <MedicationProperty CreatedDate="2013-11-14T16:41:12.76">
            <FieldName>Medication Prescribed Date</FieldName>
            <Value>08/01/2013</Value>
          </MedicationProperty>
        </MedicationProperties>
      </UserMedication>
      <UserMedication>
        <MedicationProperties>
          <MedicationProperty CreatedDate="2013-11-14T16:41:12.767">
            <FieldName>Medication Name</FieldName>
            <Value>Aspirin</Value>
          </MedicationProperty>
          <MedicationProperty CreatedDate="2013-11-14T16:41:12.77">
            <FieldName>Medication Dosage</FieldName>
            <Value>5 mg</Value>
          </MedicationProperty>
          <MedicationProperty CreatedDate="2013-11-14T16:41:12.78">
            <FieldName>Medication Prescribed Date</FieldName>
            <Value>09/01/2013</Value>
          </MedicationProperty>
        </MedicationProperties>
      </UserMedication>
      <UserMedication>
        <MedicationProperties>
          <MedicationProperty CreatedDate="2013-11-14T16:41:12.783">
            <FieldName>Medication Name</FieldName>
            <Value>Celebrex</Value>
          </MedicationProperty>
          <MedicationProperty CreatedDate="2013-11-14T16:41:12.793">
            <FieldName>Medication Dosage</FieldName>
            <Value>50 mg twice a day</Value>
          </MedicationProperty>
          <MedicationProperty CreatedDate="2013-11-14T16:41:12.8">
            <FieldName>Medication Prescribed Date</FieldName>
            <Value>10/01/2013</Value>
          </MedicationProperty>
        </MedicationProperties>
      </UserMedication>
    </UserMedications>
    <UserProperties>
      <UserProperty CreatedDate="2013-12-03T13:48:03.45">
        <FieldName>User First Name</FieldName>
        <Value>John</Value>
      </UserProperty>
      <UserProperty CreatedDate="2013-12-03T11:36:31.423">
        <FieldName>User MI</FieldName>
        <Value>Q</Value>
      </UserProperty>
      <UserProperty CreatedDate="2013-11-19T09:56:44.66">
        <FieldName>User Last Name</FieldName>
        <Value>Public</Value>
      </UserProperty>
      <UserProperty CreatedDate="2013-11-14T16:41:12.803">
        <FieldName>User SSN</FieldName>
        <Value>111-22-3333</Value>
      </UserProperty>
    </UserProperties>
  </User>
</UserInformation>

以下是我的目标:

public class EntityProperty
{
    [XmlIgnore]
    public int FieldId { get; set; }
    public string FieldName { get; set; }
    [XmlIgnore]
    public int FieldSortOrder { get; set; }
    [XmlAttribute()]
    public DateTime CreatedDate { get; set; }
    [XmlIgnore]
    public bool IsIterative { get; set; }
    public string Value { get; set; }
    public EntityTreeBase Entity { get; set; }
    public EntityProperty() { }
    public EntityProperty(int fieldId, string fieldName, int fieldSortOrder, DateTime createdDate, bool isIterative, string valueIn)
    {
        FieldId = fieldId;
        FieldName = FieldName;
        FieldSortOrder = fieldSortOrder;
        CreatedDate = createdDate;
        IsIterative = isIterative;
        Value = valueIn;
    }
}

public class EntityTreeBase
{
    [XmlIgnore]
    public long EntityId { get; set; }
    [XmlIgnore]
    public long? ParentEntityId { get; set; }
    [XmlIgnore]
    public int EntityDefinitionId { get; set; }
    [XmlIgnore]
    public int DestinationId { get; set; }
    [XmlIgnore]
    public int Level { get; set; }
    [XmlAttribute("EntityInfo")]
    public string EntityDefinitionName { get; set; }
    public EntityTreeBaseCollection Children { get; set; }
    public EntityPropertiesCollection Properties { get; set; }
    public EntityTreeBase() { }
    public EntityTreeBase(long entityId, long? parentEntityId, int entityDefinitionId, int destinationId, int level, string entityDefinitionName)
    {
        EntityId = entityId;
        ParentEntityId = parentEntityId;
        EntityDefinitionId = entityDefinitionId;
        DestinationId = destinationId;
        Level = level;
        EntityDefinitionName = entityDefinitionName;
    }
    public bool HasChildren
    {
        get { return (Children != null && Children.Count > 0); }
    }
    public bool HasProperties
    {
        get { return (Properties != null && Properties.Count > 0); }
    }
    public static EntityTreeBase BuildTree(EntityTreeBaseCollection collection, EntityTreeBase parent)
    {
        parent.Properties = EntityPropertiesCollection.GetProperties(parent.DestinationId, parent.EntityId, parent.EntityDefinitionId);
        parent.Children = new EntityTreeBaseCollection();
        foreach (EntityTreeBase item in EntityTreeBaseCollection.FindChildEntities(collection, parent.EntityId))
        {
            parent.Children.Add(BuildTree(EntityTreeBaseCollection.GetChildren(item.EntityId, item.Level, item.DestinationId), item));
        }
        if (!parent.HasChildren)
        {
            parent.Children = null;
        }
        if (!parent.HasProperties)
        {
            parent.Properties = null;
        }
        return parent;
    }
}

因此,有希望显而易见的是,没有名为“Medication”或“User”的对象类型,这些必须从数据中推断出来。所以我需要知道如何使用数据中的值来更改我的元素名称,但我需要弄清楚如何抓取对象树,以便根据关联的EntityDefinitionName更改每个元素名称。我在序列化之前使用递归来填充对象树。我知道以下代码可以重命名我的XmlRoot:

XmlAttributeOverrides xmlOverrides = new XmlAttributeOverrides();
XmlAttributes attribs = new XmlAttributes();
XmlRootAttribute rootAttr = new XmlRootAttribute();
rootAttr.ElementName = collection.Find(e => e.Level == 1).EntityDefinitionName.Replace(" ", "");
attribs.XmlRoot = rootAttr;

但我需要弄清楚如何根据与该元素或节点关联的EntityDefinitionName更改每个元素名称。

提前致谢!

1 个答案:

答案 0 :(得分:0)

虽然我认为您可以通过使用自定义序列化来实现这一点,但我希望通过使用XSLT样式表来提出解决问题的不同方法。

此样式表将输入xml转换为所需的输出xml:

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
                exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="ArrayOfEntityTreeBase">
       <UserInformation >
        <xsl:apply-templates />
       </UserInformation>
    </xsl:template>

  <xsl:template match="EntityTreeBase[@EntityInfo='User']">
    <User>
      <xsl:apply-templates />
    </User>
  </xsl:template>

  <xsl:template match="Children">
    <UserMedications>
      <xsl:apply-templates />
    </UserMedications>
  </xsl:template>

  <xsl:template match="EntityTreeBase[@EntityInfo='User Medication']">
    <UserMedication>
      <xsl:apply-templates />
    </UserMedication>
  </xsl:template>

  <xsl:template match="EntityTreeBase[@EntityInfo='User Medication']/Properties">
    <MedicationProperties>
      <xsl:apply-templates />
    </MedicationProperties>
  </xsl:template>

  <xsl:template match="EntityTreeBase[@EntityInfo='User']/Properties">
    <UserProperties>
      <xsl:apply-templates/>
    </UserProperties>
  </xsl:template>

  <xsl:template match="EntityTreeBase[@EntityInfo='User']/Properties/EntityProperty">
    <xsl:element name="UserProperty">
      <xsl:copy-of select="@*"/>
      <xsl:copy-of select="*" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="EntityTreeBase[@EntityInfo='User Medication']/Properties/EntityProperty">
    <xsl:element name="MedicationProperty">
      <xsl:copy-of select="@*"/>
       <xsl:copy-of select="*" />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

这是您可以使用c#代码运行转换的代码:

 var xml = File.Open("input.xml", FileMode.Open); // or any stream
 var xslTrans = new XslCompiledTransform();
 xslTrans.Load(XmlReader.Create(File.Open("yourxslfile.xlst", FileMode.Open)));
 var output = File.Create("output.xml");  // or a stream
 var xw = XmlWriter.Create(output);
 xslTrans.Transform(XmlReader.Create(xml), xw );
 xw.Close();