【问题标题】:How to read different XML Elements in single class property?如何在单个类属性中读取不同的 XML 元素?
【发布时间】:2019-12-30 10:44:38
【问题描述】:

我有一个xsd.exe 输出 c# 类:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class OrdinateZacrep
{

    private decimal xField;

    private decimal yField;

    /// <remarks/>
    public decimal x
    {
        get
        {
            return this.xField;
        }
        set
        {
            this.xField = value;
        }
    }

    /// <remarks/>
    public decimal y
    {
        get
        {
            return this.yField;
        }
        set
        {
            this.yField = value;
        }
    }
}

XML 很简单:

<ordinate>
 <x>587865.52</x>
 <y>1397457.84</y>
</ordinate>

但有时 XML 看起来像:

<ordinate>
 <x>587865.52</x>
 <_y>1397457.84</_y>
</ordinate>

我怎样才能用单课阅读这个简单的东西?

这里是 xsd 切片:

<xsd:complexType name="OrdinateOut">
        <xsd:annotation>
            <xsd:documentation>Parcel coordinates</xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="x" type="xsd:decimal">
                <xsd:annotation>
                    <xsd:documentation>Ordinate X</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
            <xsd:element name="y" type="xsd:decimal">
                <xsd:annotation>
                    <xsd:documentation>Ordinate Y</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
        </xsd:sequence>
    </xsd:complexType>

【问题讨论】:

  • 什么会在 xml 文件中产生 _y 元素?你能给我们看看你的 xsd 文件吗?
  • @Samuel _y 对于 xsd 架构无效。但是这里有太多带有_y的xml文档,我不能忽略它。
  • 不熟悉 C# 代码,这个问题是关于更改自动生成 XSD 的 C# 代码,还是关于更改 XSD 以使您显示的两个 XML 文档都有效?

标签: c# xml xsd


【解决方案1】:

您正在使用私有变量 xField 和 yField。所以只需创建一个新属性,像这样保存到 xField 和 yField

public decimal _y
{
   get
   {
      return this.yField;
   }
   set
   {
      this.yField = value;
   }
}

【讨论】:

  • 我认为实际尝试修改(生成的)模式文件以强制它根据模式规范接受无效元素是有问题的。我宁愿建议创建一个翻译步骤来将无效的 xml 文件翻译成有效的 xml 文件。我认为这会产生更清晰的 C# 代码,因为这样您就不会在代码本身中处理不兼容的 xml 文件。您对此有何看法?
  • 我并不是说要修改架构。曾经生成文件的人从未做过模式检查。我只是说最好的解决方案就是通过添加额外的属性来修改类。这是最好的选择,除非您想使用您所说的其他网络库方法自定义解析整个 xml。
  • 如果我错了,请纠正我:无论如何,他都需要调整生成代码的架构,以实际引入使用 y_y 的能力,否则 XML 解析器将不会’真的无法阅读,还是我错了?如果设置了_y,但没有设置y,解析器应该怎么做? y 不可为空,因此它要么使用throw,要么使用default(decimal),而xml 文件的使用者不知道要使用哪个字段?
  • 反序列化时不会自动完成架构检查(即使架构可能在 xml 中)。所以不需要改变模式。如果您返回并使用 xsd.exe 之类的工具自动创建类,那么每次运行 xsd.exe 时都需要添加新属性。但希望在生成新的 xml 文件时可以解决这个问题,所以问题只是一个临时修复,直到根本原因得到解决。我可能不会包含 set 属性,所以只有读数会寻找 _y
  • @jdweng 您的解决方案运行良好。确实,这是临时解决方案,因为当前的 xsd 架构只是一个项目,尚未正式接受。
【解决方案2】:

一种可能的解决方案是应用 xslt 来转换 xml 文件,而不是根据您的架构作为预处理步骤。应用于已经正确格式化的 xml 文件应该是安全的。

例如,此 xslt 将所有 ordinate/_y 元素重命名为 ordinate/y

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="ordinate/_y">
        <y><xsl:apply-templates select="@*|node()" /></y>
    </xsl:template>
</xsl:stylesheet>

您可以在page 上对其进行测试,并且有关于如何在 C# 中使用 XSLT 的示例,只需 google 即可:)

编辑:我忘记了蛮力方法:在解析文件之前,字符串替换文件中的&lt;_y&gt;&lt;/_y&gt;。我不建议这样做,但它可能是一个解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    相关资源
    最近更新 更多