Linq XElement在foreach中更改值格式

时间:2013-05-07 13:23:28

标签: .net xml linq linq-to-xml

这看起来很奇怪(除非我遗漏了一些明显的东西)。我必须存储这个字符串:

{TestField1:=TestAltField1}{TestField2:=TestAltField2}

在XML Value字段中产生如下内容:

<ResultFieldAlias>{TestField1:=TestAltField1}{TestField2:=TestAltField2}</ResultFieldAlias>

该值将存储在字符串,字符串字典中。但是当我尝试在foreach循环和反射中将它从XElement“XML”的XElements中拉出来时,它会更改括号并删除冒号,从而导致:

[TestField1, TestAltField1][TestField2, TestAltField2]

以下是我用来通过Reflections获取属性的代码:

PropertyInfo[] properties = GetPublicProperties();

//loop through each entry in the dictionary and try to find its matching property
foreach (XE xe in XML.Elements())
{
    //Try to find a matching prop to this key
    PropertyInfo prop = properties.FirstOrDefault(p => p.Name.ToLower() == xe.Name.ToString().ToLower());

    if (prop != null)
        if (prop.PropertyType == typeof(bool))
            prop.SetValue(this, bool.Parse(xe.Value), null);
        else if (prop.PropertyType == typeof(FontSettings))
            prop.SetValue(this, new FontSettings(xe), null);
        else if (prop.PropertyType == typeof(Dictionary<string, string>))
            prop.SetValue(this, MyExtension.Deserialize(xe.Value), null);
        else
            prop.SetValue(this, xe.Value, null);
}

请注意反序列化函数,该函数期望格式为curlies和:=。当我调试它时,如果我查看循环中的xe对象,我会从即时窗口得到它:

? xe
<ResultFieldAlias>[TestField1, TestAltField1][TestField2, TestAltField2]</ResultFieldAlias>
    base {System.Xml.Linq.XContainer}: <ResultFieldAlias>[TestField1, TestAltField1][TestField2, TestAltField2]</ResultFieldAlias>
    FirstAttribute: null
    HasAttributes: false
    HasElements: false
    IsEmpty: false
    lastAttr: null
    LastAttribute: null
    Name: {ResultFieldAlias}
    name: {ResultFieldAlias}
    NodeType: Element
    Value: "[TestField1, TestAltField1][TestField2, TestAltField2]"

但是,如果我根据XML的最后一个元素创建一个全新的XElement(在它发生的地方,它之前有一堆),我得到了正确的格式:

? XElement xe1 =  XML.Elements().Last();
<ResultFieldAlias>{TestField1:=TestAltField1}{TestField2:=TestAltField2}</ResultFieldAlias>
    base {System.Xml.Linq.XContainer}: <ResultFieldAlias>{TestField1:=TestAltField1}{TestField2:=TestAltField2}</ResultFieldAlias>
    FirstAttribute: null
    HasAttributes: false
    HasElements: false
    IsEmpty: false
    lastAttr: null
    LastAttribute: null
    Name: {ResultFieldAlias}
    name: {ResultFieldAlias}
    NodeType: Element
    Value: "{TestField1:=TestAltField1}{TestField2:=TestAltField2}"

是什么给出的?感谢。

更新

要回答Jeffs评论并添加信息,XML对象(XElement)将传递给此函数。 TestFields是使用字符串的Add方法添加的,字符串字典名为“ResultFieldAlias”,然后在被XML标记“ResultFieldAlias”包装之前使用此函数转换为字符串:

public static string Serialize(Dictionary<string, string> data)
{
    if (data == null) 
        return null;

    return "{" + String.Join("}{", data.Select(c => c.Key + ":=" + c.Value).ToArray()) + "}";
}

结果如下(只有它的尾部 - 发布会很大):

<Callouts>
    .....
    .....   
  <ResultExceedFont>
    <FontSettings>
      <FontName>Curlz MT</FontName>
      <FontColor>#FF6B8E23</FontColor>
      <FontSize>15</FontSize>
      <FontUnderline>false</FontUnderline>
      <FontBold>false</FontBold>
      <FontItalic>true</FontItalic>
    </FontSettings>
  </ResultExceedFont>
  <ResultFieldAlias>{TestField1:=TestAltField1}{TestField2:=TestAltField2}</ResultFieldAlias>
</Callouts>

我在VS中的我的立即窗口中有两个以前的代码粘贴(在开始时的?)是在一行“prop.SetValue(this,MyExtension.Deserialize(xe.Value)”处获取的,空值);”所以他们同时打同一个XML对象。这是精确的剪切和粘贴(再次,缩短了XML转储):

? XML
....
  <ResultExceedFont>
    <FontSettings>
      <FontName>Curlz MT</FontName>
      <FontColor>#FF6B8E23</FontColor>
      <FontSize>15</FontSize>
      <FontUnderline>false</FontUnderline>
      <FontBold>false</FontBold>
      <FontItalic>true</FontItalic>
    </FontSettings>
  </ResultExceedFont>
  <ResultFieldAlias>{TestField1:=TestAltField1}{TestField2:=TestAltField2}</ResultFieldAlias>
</Callouts>
    FirstAttribute: null
    HasAttributes: false
    HasElements: true
    IsEmpty: false
    lastAttr: null
    LastAttribute: null
    Name: {Callouts}
    name: {Callouts}
    NodeType: Element
    Value: "falsefalsefalsefalsefalsefalsefalsefalsefalsefalsefalsefalsefalsefalse[TestField1, TestAltField1][TestField2, TestAltField2]falsefalseBalloonfalse#FFFFFF00Adobe Song Std#FF228B2210truetruetrueAdobe Ming Std#FFF0808010truetruetrueAdobe Kaiti Std#FFDC143C20truefalsetrueCurlz MT#FF6B8E2315falsefalsetrue{TestField1:=TestAltField1}{TestField2:=TestAltField2}"
?xe
<ResultFieldAlias>[TestField1, TestAltField1][TestField2, TestAltField2]</ResultFieldAlias>
    base {System.Xml.Linq.XContainer}: <ResultFieldAlias>[TestField1, TestAltField1][TestField2, TestAltField2]</ResultFieldAlias>
    FirstAttribute: null
    HasAttributes: false
    HasElements: false
    IsEmpty: false
    lastAttr: null
    LastAttribute: null
    Name: {ResultFieldAlias}
    name: {ResultFieldAlias}
    NodeType: Element
    Value: "[TestField1, TestAltField1][TestField2, TestAltField2]"
?XML.Elements().Last()
<ResultFieldAlias>{TestField1:=TestAltField1}{TestField2:=TestAltField2}</ResultFieldAlias>
    base {System.Xml.Linq.XContainer}: <ResultFieldAlias>{TestField1:=TestAltField1}{TestField2:=TestAltField2}</ResultFieldAlias>
    FirstAttribute: null
    HasAttributes: false
    HasElements: false
    IsEmpty: false
    lastAttr: null
    LastAttribute: null
    Name: {ResultFieldAlias}
    name: {ResultFieldAlias}
    NodeType: Element
    Value: "{TestField1:=TestAltField1}{TestField2:=TestAltField2}"

1 个答案:

答案 0 :(得分:0)

没关系!啊......愚蠢....它说明我在构建XML时没有正确过滤并添加了ResultFieldAlias字典TWICE。第一个实例是由字典的默认ToString()方法创建的 - 因此格式化。所以xe var抓住那个,因为它是第一个但我的.Last()测试抓住了第二个正确的版本。

抱歉无用的帖子。谢谢Jeff让我仔细看看。

欧尼