C# 反序列化问题 xml 数组中的数组和其他名称
C# Problem with deserialization xml with arrays in arrays and other names
我在创建适当的 class 以反序列化 xml 文件时遇到问题。 xml 结构如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="pl" datatype="plaintext" original="1112">
<body>
<group id="90362">
<trans-unit id="90362::aff_11">
<source>text 1 1</source>
<target>text 1 1</target>
</trans-unit>
<trans-unit id="90362::aff_12">
<source>text 1 2</source>
<target>text 1 2</target>
</trans-unit>
<trans-unit id="90362::aff_13">
<source>text 1 3</source>
<target>text 1 3</target>
</trans-unit>
</group>
<group id="90392">
<trans-unit id="90392::aff_21">
<source>text 2 1</source>
<target>text 2 1</target>
</trans-unit>
<trans-unit id="90392::aff_22">
<source>text 2 2</source>
<target>text 2 2</target>
</trans-unit>
<trans-unit id="90392::aff_23">
<source>text 2 3</source>
<target>text 2 3</target>
</trans-unit>
</group>
</body>
</file>
</xliff>
如您所见,我们在数组中嵌套了数组。此外,其中一个数组的名称不能与 class 的名称相同。预先创建 classes:
[XmlRoot("xliff", Namespace = "urn:oasis:names:tc:xliff:document:1.2")]
public class xliff
{
public file file { get; set; }
}
public class file
{
public body body { get; set; }
}
public class body : List<group>
{
public List<group> groups { get; set; }
}
public class group //: List<trans>
{
public List<trans> trans { get; set; }
}
public class trans
{
[XmlElement("source")]
public string source { get; set; }
[XmlElement("target")]
public string target { get; set; }
}
不幸的是,我无法完成 classes 以获取源值和目标值。
you should not inherit from List<T>
. Instead chose composition over inheritance,这意味着您的 body
-class 有 组集合,与您的 body
形成对比-class就是这样的合集。
所以你可以改用这个结构:
[XmlRoot("xliff", Namespace = "urn:oasis:names:tc:xliff:document:1.2")]
public class xliff
{
public file file { get; set; }
}
public class file
{
public body body { get; set; }
}
public class body
{
[XmlElement("group")]
public List<group> groups { get; set; }
}
public class group
{
[XmlElement("trans")]
public List<trans> trans { get; set; }
}
public class trans
{
[XmlElement("source")]
public string source { get; set; }
[XmlElement("target")]
public string target { get; set; }
}
此外,您应该考虑为您的 classes 使用 PascalCase。要在序列化的 xml 中给这些 classes 不同的名称,您可以使用 xml 属性,例如:
[XmlRott("body")]
public class Body
您可以使用在线工具将 XML 转换为 c# 模型:https://json2csharp.com/xml-to-csharp
尝试使用此模型(由上述工具生成):
// using System.Xml.Serialization;
// XmlSerializer serializer = new XmlSerializer(typeof(Xliff));
// using (StringReader reader = new StringReader(xml))
// {
// var test = (Xliff)serializer.Deserialize(reader);
// }
[XmlRoot(ElementName="trans-unit")]
public class Transunit {
[XmlElement(ElementName="source")]
public string Source { get; set; }
[XmlElement(ElementName="target")]
public string Target { get; set; }
[XmlAttribute(AttributeName="id")]
public string Id { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName="group")]
public class Group {
[XmlElement(ElementName="transunit")]
public List<Transunit> Transunit { get; set; }
[XmlAttribute(AttributeName="id")]
public int Id { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName="body")]
public class Body {
[XmlElement(ElementName="group")]
public List<Group> Group { get; set; }
}
[XmlRoot(ElementName="file")]
public class File {
[XmlElement(ElementName="body")]
public Body Body { get; set; }
[XmlAttribute(AttributeName="source-language")]
public string SourceLanguage { get; set; }
[XmlAttribute(AttributeName="target-language")]
public string TargetLanguage { get; set; }
[XmlAttribute(AttributeName="datatype")]
public string Datatype { get; set; }
[XmlAttribute(AttributeName="original")]
public int Original { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName="xliff")]
public class Xliff {
[XmlElement(ElementName="file")]
public File File { get; set; }
[XmlAttribute(AttributeName="version")]
public DateTime Version { get; set; }
[XmlAttribute(AttributeName="xmlns")]
public string Xmlns { get; set; }
[XmlText]
public string Text { get; set; }
}
XLIFF 比这复杂得多,元素也多得多。当前版本是 2.1,但更旧的 1.2 也在 the OASIS site, along with links to the XSD schema
中描述
几乎所有标准化的 XML 文档都基于 XML 模式,可作为 XSD 文档(XML 模式定义)获得。
您可以使用 xsd.exe
工具从 XSD 文件生成 C# 类。你可以下载例如 http://docs.oasis-open.org/xliff/v1.2/cs02/xliff-core-1.2-strict.xsd
本地为 xliff.xsd
然后执行
xsd xliff.xsd /c
生成包含所有 类 的文件 xliff.cs
。
结果超过1000行,不能直接贴在这里
从文档复制的 tree structure 有 lot 个元素:
<xliff>1
| |
| +--- [Extension Point]
| |
+--- <file>+
|
+--- <header>?
| |
| +--- <skl>?
| | |
| | +--- (<internal-file> | <external-file>)1
| |
| +--- <phase-group>?
| | |
| | +--- <phase>+
| | |
| | +--- <note>*
| |
| +--- <glossary>*
| | |
| | +--- (<internal-file> | <external-file>)1
| |
| +--- <reference>*
| | |
| | +--- (<internal-file> | <external-file>)1
| |
| +--- <count-group>*
| | |
| | +--- <count>*
| |
| +--- <tool>*
| | |
| | +--- [Extension Point]
| |
| +--- <prop-group>*
| | |
| | +--- <prop>*
| |
| +--- [Extension Point]
| |
| +--- <note>*
|
+--- <body>1
|
+--- <group>*
| |
| +--- <context-group>*
| | |
| | +--- <context>+
| |
| +--- <count-group>*
| | |
| | +--- <count>*
| |
| +--- <prop-group>*
| | |
| | +--- <prop>*
| |
| +--- [Extension Point]
| |
| +--- <note>*
| |
| +--- At least one of: (<group>* <trans-unit>* <bin-unit>*)
|
+--- <trans-unit>*
| |
| +--- <source>1
| | |
| | +--- [Inline Elements]
| |
| +--- <target>?
| | |
| | +--- [Inline Elements]
| |
| +--- <context-group>*
| | |
| | +--- <context>+
| |
| +--- <count-group>*
| | |
| | +--- <count>*
| |
| +--- <prop-group>*
| | |
| | +--- <prop>*
| |
| +--- <seg-source>?
| | |
| | +--- [Inline Elements]
| |
| +--- [Extension Point]
| |
| +--- <note>*
| |
| +--- <alt-trans>*
| |
| +--- <context-group>*
| | |
| | +--- <context>+
| |
| +--- <source>?
| | |
| | +--- [Inline Elements]
| | | +--- <target>+
| | |
| | +--- [Inline Elements]
| |
| +--- <prop-group>*
| | |
| | +--- <prop>*
| |
| +--- <seg-source>?
| | |
| | +--- [Inline Elements]
| |
| +--- [Extension Point]
| |
| +---- <note>*
|
+--- <bin-unit>*
|
+--- <bin-source>1 & <bin-target>?
| |
| +--- (<internal-file> | <external-file>)1
|
+--- <context-group>*
| |
| +--- <context>+
|
+--- <count-group>*
| |
| +--- <count>*
|
+--- <prop-group>*
| |
| +--- <prop>*
|
+--- [Extension Point]
|
+--- <note>*
|
+--- <trans-unit>*
Struct_Extension_Elements
Inline Elements:
---+--- <ph>*
| |
| +--- <sub>*
| |
| +--- [Inline Elements]
|
+--- <it>*
| |
| +--- <sub>*
| |
| +--- [Inline Elements]
|
+--- <bpt>*
| |
| +--- <sub>*
| |
| +--- [Inline Elements]
|
+--- <ept>*
| |
| +--- <sub>*
| |
| +--- [Inline Elements]
|
+--- <g>*
| |
| +--- [Inline Elements]
|
+--- <x/>*
| |
| +--- [Inline Elements]
|
+--- <bx/>*
| |
| +--- [Inline Elements]
|
+--- <ex/>*
| |
| +--- [Inline Elements]
|
+--- <mrk>*
|
+--- [Inline Elements]
这是使用 Cinchoo ETL 从 xml 中提取部分数据的另一种方法 - 一个开源库,无需创建分层 classes(使用 xsd.exe)
方法一:用POCOclass
定义 POCO class
public class trans
{
[XmlElement("source")]
public string source { get; set; }
[XmlElement("target")]
public string target { get; set; }
}
使用 ChoXmlReader 解析和加载 xml,如下所示
using (var r = new ChoXmlReader<trans>("*** XML FILE PATH ***")
.WithXPath("//trans-unit")
.WithXmlNamespace("x", "urn:oasis:names:tc:xliff:document:1.2"))
{
foreach (var rec in r)
rec.Print();
}
示例 fiddle: https://dotnetfiddle.net/rsKZiQ
方法二:使用动态
使用 ChoXmlReader 解析和加载 xml,如下所示
using (var r = new ChoXmlReader("*** XML FILE PATH ***")
.WithXPath("//trans-unit")
.WithXmlNamespace("x", "urn:oasis:names:tc:xliff:document:1.2"))
{
foreach (var rec in r)
rec.Print();
}
示例 fiddle: https://dotnetfiddle.net/Xg3x7K
免责声明:我是该库的作者。
我在创建适当的 class 以反序列化 xml 文件时遇到问题。 xml 结构如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="pl" datatype="plaintext" original="1112">
<body>
<group id="90362">
<trans-unit id="90362::aff_11">
<source>text 1 1</source>
<target>text 1 1</target>
</trans-unit>
<trans-unit id="90362::aff_12">
<source>text 1 2</source>
<target>text 1 2</target>
</trans-unit>
<trans-unit id="90362::aff_13">
<source>text 1 3</source>
<target>text 1 3</target>
</trans-unit>
</group>
<group id="90392">
<trans-unit id="90392::aff_21">
<source>text 2 1</source>
<target>text 2 1</target>
</trans-unit>
<trans-unit id="90392::aff_22">
<source>text 2 2</source>
<target>text 2 2</target>
</trans-unit>
<trans-unit id="90392::aff_23">
<source>text 2 3</source>
<target>text 2 3</target>
</trans-unit>
</group>
</body>
</file>
</xliff>
如您所见,我们在数组中嵌套了数组。此外,其中一个数组的名称不能与 class 的名称相同。预先创建 classes:
[XmlRoot("xliff", Namespace = "urn:oasis:names:tc:xliff:document:1.2")]
public class xliff
{
public file file { get; set; }
}
public class file
{
public body body { get; set; }
}
public class body : List<group>
{
public List<group> groups { get; set; }
}
public class group //: List<trans>
{
public List<trans> trans { get; set; }
}
public class trans
{
[XmlElement("source")]
public string source { get; set; }
[XmlElement("target")]
public string target { get; set; }
}
不幸的是,我无法完成 classes 以获取源值和目标值。
you should not inherit from List<T>
. Instead chose composition over inheritance,这意味着您的 body
-class 有 组集合,与您的 body
形成对比-class就是这样的合集。
所以你可以改用这个结构:
[XmlRoot("xliff", Namespace = "urn:oasis:names:tc:xliff:document:1.2")]
public class xliff
{
public file file { get; set; }
}
public class file
{
public body body { get; set; }
}
public class body
{
[XmlElement("group")]
public List<group> groups { get; set; }
}
public class group
{
[XmlElement("trans")]
public List<trans> trans { get; set; }
}
public class trans
{
[XmlElement("source")]
public string source { get; set; }
[XmlElement("target")]
public string target { get; set; }
}
此外,您应该考虑为您的 classes 使用 PascalCase。要在序列化的 xml 中给这些 classes 不同的名称,您可以使用 xml 属性,例如:
[XmlRott("body")]
public class Body
您可以使用在线工具将 XML 转换为 c# 模型:https://json2csharp.com/xml-to-csharp
尝试使用此模型(由上述工具生成):
// using System.Xml.Serialization;
// XmlSerializer serializer = new XmlSerializer(typeof(Xliff));
// using (StringReader reader = new StringReader(xml))
// {
// var test = (Xliff)serializer.Deserialize(reader);
// }
[XmlRoot(ElementName="trans-unit")]
public class Transunit {
[XmlElement(ElementName="source")]
public string Source { get; set; }
[XmlElement(ElementName="target")]
public string Target { get; set; }
[XmlAttribute(AttributeName="id")]
public string Id { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName="group")]
public class Group {
[XmlElement(ElementName="transunit")]
public List<Transunit> Transunit { get; set; }
[XmlAttribute(AttributeName="id")]
public int Id { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName="body")]
public class Body {
[XmlElement(ElementName="group")]
public List<Group> Group { get; set; }
}
[XmlRoot(ElementName="file")]
public class File {
[XmlElement(ElementName="body")]
public Body Body { get; set; }
[XmlAttribute(AttributeName="source-language")]
public string SourceLanguage { get; set; }
[XmlAttribute(AttributeName="target-language")]
public string TargetLanguage { get; set; }
[XmlAttribute(AttributeName="datatype")]
public string Datatype { get; set; }
[XmlAttribute(AttributeName="original")]
public int Original { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName="xliff")]
public class Xliff {
[XmlElement(ElementName="file")]
public File File { get; set; }
[XmlAttribute(AttributeName="version")]
public DateTime Version { get; set; }
[XmlAttribute(AttributeName="xmlns")]
public string Xmlns { get; set; }
[XmlText]
public string Text { get; set; }
}
XLIFF 比这复杂得多,元素也多得多。当前版本是 2.1,但更旧的 1.2 也在 the OASIS site, along with links to the XSD schema
中描述几乎所有标准化的 XML 文档都基于 XML 模式,可作为 XSD 文档(XML 模式定义)获得。
您可以使用 xsd.exe
工具从 XSD 文件生成 C# 类。你可以下载例如 http://docs.oasis-open.org/xliff/v1.2/cs02/xliff-core-1.2-strict.xsd
本地为 xliff.xsd
然后执行
xsd xliff.xsd /c
生成包含所有 类 的文件 xliff.cs
。
结果超过1000行,不能直接贴在这里
从文档复制的 tree structure 有 lot 个元素:
<xliff>1
| |
| +--- [Extension Point]
| |
+--- <file>+
|
+--- <header>?
| |
| +--- <skl>?
| | |
| | +--- (<internal-file> | <external-file>)1
| |
| +--- <phase-group>?
| | |
| | +--- <phase>+
| | |
| | +--- <note>*
| |
| +--- <glossary>*
| | |
| | +--- (<internal-file> | <external-file>)1
| |
| +--- <reference>*
| | |
| | +--- (<internal-file> | <external-file>)1
| |
| +--- <count-group>*
| | |
| | +--- <count>*
| |
| +--- <tool>*
| | |
| | +--- [Extension Point]
| |
| +--- <prop-group>*
| | |
| | +--- <prop>*
| |
| +--- [Extension Point]
| |
| +--- <note>*
|
+--- <body>1
|
+--- <group>*
| |
| +--- <context-group>*
| | |
| | +--- <context>+
| |
| +--- <count-group>*
| | |
| | +--- <count>*
| |
| +--- <prop-group>*
| | |
| | +--- <prop>*
| |
| +--- [Extension Point]
| |
| +--- <note>*
| |
| +--- At least one of: (<group>* <trans-unit>* <bin-unit>*)
|
+--- <trans-unit>*
| |
| +--- <source>1
| | |
| | +--- [Inline Elements]
| |
| +--- <target>?
| | |
| | +--- [Inline Elements]
| |
| +--- <context-group>*
| | |
| | +--- <context>+
| |
| +--- <count-group>*
| | |
| | +--- <count>*
| |
| +--- <prop-group>*
| | |
| | +--- <prop>*
| |
| +--- <seg-source>?
| | |
| | +--- [Inline Elements]
| |
| +--- [Extension Point]
| |
| +--- <note>*
| |
| +--- <alt-trans>*
| |
| +--- <context-group>*
| | |
| | +--- <context>+
| |
| +--- <source>?
| | |
| | +--- [Inline Elements]
| | | +--- <target>+
| | |
| | +--- [Inline Elements]
| |
| +--- <prop-group>*
| | |
| | +--- <prop>*
| |
| +--- <seg-source>?
| | |
| | +--- [Inline Elements]
| |
| +--- [Extension Point]
| |
| +---- <note>*
|
+--- <bin-unit>*
|
+--- <bin-source>1 & <bin-target>?
| |
| +--- (<internal-file> | <external-file>)1
|
+--- <context-group>*
| |
| +--- <context>+
|
+--- <count-group>*
| |
| +--- <count>*
|
+--- <prop-group>*
| |
| +--- <prop>*
|
+--- [Extension Point]
|
+--- <note>*
|
+--- <trans-unit>*
Struct_Extension_Elements
Inline Elements:
---+--- <ph>*
| |
| +--- <sub>*
| |
| +--- [Inline Elements]
|
+--- <it>*
| |
| +--- <sub>*
| |
| +--- [Inline Elements]
|
+--- <bpt>*
| |
| +--- <sub>*
| |
| +--- [Inline Elements]
|
+--- <ept>*
| |
| +--- <sub>*
| |
| +--- [Inline Elements]
|
+--- <g>*
| |
| +--- [Inline Elements]
|
+--- <x/>*
| |
| +--- [Inline Elements]
|
+--- <bx/>*
| |
| +--- [Inline Elements]
|
+--- <ex/>*
| |
| +--- [Inline Elements]
|
+--- <mrk>*
|
+--- [Inline Elements]
这是使用 Cinchoo ETL 从 xml 中提取部分数据的另一种方法 - 一个开源库,无需创建分层 classes(使用 xsd.exe)
方法一:用POCOclass
定义 POCO class
public class trans
{
[XmlElement("source")]
public string source { get; set; }
[XmlElement("target")]
public string target { get; set; }
}
使用 ChoXmlReader 解析和加载 xml,如下所示
using (var r = new ChoXmlReader<trans>("*** XML FILE PATH ***")
.WithXPath("//trans-unit")
.WithXmlNamespace("x", "urn:oasis:names:tc:xliff:document:1.2"))
{
foreach (var rec in r)
rec.Print();
}
示例 fiddle: https://dotnetfiddle.net/rsKZiQ
方法二:使用动态
使用 ChoXmlReader 解析和加载 xml,如下所示
using (var r = new ChoXmlReader("*** XML FILE PATH ***")
.WithXPath("//trans-unit")
.WithXmlNamespace("x", "urn:oasis:names:tc:xliff:document:1.2"))
{
foreach (var rec in r)
rec.Print();
}
示例 fiddle: https://dotnetfiddle.net/Xg3x7K
免责声明:我是该库的作者。