【问题标题】:The relationship between DataTables in DataSet: can we check if the parent is so and so?DataSet中DataTables之间的关系:我们可以检查父级是否是某某吗?
【发布时间】:2021-01-31 03:30:15
【问题描述】:

我加载了一个包含大量数据的复杂 XML 文件,其中包含复杂级别的嵌套元素。 DataSet.ReadXml() 加载得很好,我可以遍历所有节点。

基本上每个节点都被选为 DataTable,属性作为列名。

现在我可以像这样以线性方式遍历所有这些元素/数据表:

    foreach( DataTable curDT in DS.Tables)
    {
        Console.WriteLine("Table name: {0}",curDT.TableName);
        Console.WriteLine("Columns Count: {0}", curDT.Columns.Count);
        Console.WriteLine("Rows Count: {0}", curDT.Rows.Count);
        Console.WriteLine("Container: {0}", curDT.Container);

        Console.WriteLine("columns =>");

        foreach(DataColumn dataColumn in curDT.Columns)
        {
            Console.WriteLine(dataColumn.ColumnName);
        }

        Console.WriteLine();
    }

但是这些数据表或元素之间存在复杂的嵌套关系(一个在另一个内部)。

当我使用 WriteXml() 提供新文件名时,它会正确地重新创建文件。

我的确切问题是DataSet.Tables 列表之间没有明显的关系,所以它如何能够将所有累积的 DataTables 放在一个线性列表中,但它们又能正确地重现 xml 文件。另外我想检查一下某某的父母是不是这个!

更新

我正在解析 15000 长的 STIG xml 文件,该文件可在线获取,但如果有帮助,我将开始使用它。

<Benchmark xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cpe="http://cpe.mitre.org/language/2.0" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:dc="http://purl.org/dc/elements/1.1/" id="Windows_10_STIG" xml:lang="en" xsi:schemaLocation="http://checklists.nist.gov/xccdf/1.1 http://nvd.nist.gov/schema/xccdf-1.1.4.xsd http://cpe.mitre.org/dictionary/2.0 http://cpe.mitre.org/files/cpe-dictionary_2.1.xsd" xmlns="http://checklists.nist.gov/xccdf/1.1">
  <status date="2020-06-15">accepted</status>
  <title>Windows 10 Security Technical Implementation Guide</title>
  <description>The Windows 10 Security Technical Implementation Guide (STIG) is published as a tool to improve the security of Department of Defense (DoD) information systems. Comments or proposed revisions to this document should be sent via e-mail to the following address: disa.stig_spt@mail.mil.</description>
  <notice id="terms-of-use" xml:lang="en">Developed_by_DISA_for_the_DoD</notice>
  <reference href="https://cyber.mil/">
    <dc:publisher>DISA</dc:publisher>
    <dc:source>STIG.DOD.MIL</dc:source>
  </reference>
  <plain-text id="release-info">Release: 23 Benchmark Date: 17 Jun 2020</plain-text>
  <version>1</version>
  <Profile id="MAC-1_Classified">
    <title>I - Mission Critical Classified</title>
    <description>&lt;ProfileDescription&gt;&lt;/ProfileDescription&gt;</description>
    <select idref="V-63319" selected="true" />
    <select idref="V-63321" selected="true" />
    <select idref="V-63323" selected="true" />
    <select idref="V-63325" selected="true" />
 </Profile>
  <Group id="V-63319">
    <title>WN10-00-000005</title>
    <description>&lt;GroupDescription&gt;&lt;/GroupDescription&gt;</description>
    <Rule id="SV-77809r3_rule" severity="medium" weight="10.0">
      <version>WN10-00-000005</version>
      <title>Domain-joined systems must use Windows 10 Enterprise Edition 64-bit version.</title>
      <description>&lt;VulnDiscussion&gt;Features such as Credential Guard use virtualization based security to protect information that could be used in credential theft attacks if compromised. There are a number of system requirements that must be met in order for Credential Guard to be configured and enabled properly. Virtualization based security and Credential Guard are only available with Windows 10 Enterprise 64-bit version.&lt;/VulnDiscussion&gt;&lt;FalsePositives&gt;&lt;/FalsePositives&gt;&lt;FalseNegatives&gt;&lt;/FalseNegatives&gt;&lt;Documentable&gt;false&lt;/Documentable&gt;&lt;Mitigations&gt;&lt;/Mitigations&gt;&lt;SeverityOverrideGuidance&gt;&lt;/SeverityOverrideGuidance&gt;&lt;PotentialImpacts&gt;&lt;/PotentialImpacts&gt;&lt;ThirdPartyTools&gt;&lt;/ThirdPartyTools&gt;&lt;MitigationControl&gt;&lt;/MitigationControl&gt;&lt;Responsibility&gt;&lt;/Responsibility&gt;&lt;IAControls&gt;&lt;/IAControls&gt;</description>
      <reference>
        <dc:title>DPMS Target Windows 10</dc:title>
        <dc:publisher>DISA</dc:publisher>
        <dc:type>DPMS Target</dc:type>
        <dc:subject>Windows 10</dc:subject>
        <dc:identifier>2885</dc:identifier>
      </reference>
      <ident system="http://iase.disa.mil/cci">CCI-000366</ident>
      <fixtext fixref="F-69237r2_fix">Use Windows 10 Enterprise 64-bit version for domain-joined systems.</fixtext>
      <fix id="F-69237r2_fix" />
      <check system="C-64053r3_chk">
        <check-content-ref name="M" href="DPMS_XCCDF_Benchmark_Windows_10_STIG.xml" />
        <check-content>
          Verify domain-joined systems are using Windows 10 Enterprise Edition 64-bit version.

          For standalone systems, this is NA.

          Open "Settings".

          Select "System", then "About".

          If "Edition" is not "Windows 10 Enterprise", this is a finding.

          If "System type" is not "64-bit operating system…", this is a finding.
        </check-content>
      </check>
    </Rule>
  </Group>

文件一直在继续。我以它代表复杂性的方式提供了文件的开头。

【问题讨论】:

  • 为了回答,最好有一个您正在解析的 XML 数据的示例,无论是假数据还是重新创建的数据,这将有助于您获得答案。
  • @Jimithus 我正在解析 stigs XML 文件,这是 zip 文件夹中在线提供的 15000 行文件,但如果有帮助,我会发布它的开头。
  • 即使你只有 2 个元素来显示复杂性,它也会有所帮助。
  • 使用 excel 工作簿来设计你的数据集。工作簿的每张表都是不同的数据表。标题行将是数据表的列。对于每个文件,您需要通过一个公共键(如 xml 文件中的文件名或属性)来链接工作表(数据表)。我会试一试。

标签: c# xml ado.net


【解决方案1】:

我使用 Xml Linq 来解析 xml 以保持较少的级别数。使用 xml linq,您可以将后代组合成一个对象。我还使用了类而不是表。请参阅下面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string URL = "https://www.stigviewer.com/stig/windows_10/2020-06-15/MAC-3_Sensitive/xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(URL);
            XElement benchmark = doc.Root;
            XNamespace ns = benchmark.GetDefaultNamespace();
            XNamespace nsDc = benchmark.GetNamespaceOfPrefix("dc");

            Header header = new Header(ns, nsDc, benchmark);
            Profiles profiles = new Profiles(ns, benchmark);
            Group groups = new Group(ns, nsDc, benchmark);

            
        }
    }
    public class Header
    {
        public string status { get; set; }
        public DateTime date { get; set; }
        public string title { get; set; }
        public string description { get; set; }
        public string notice { get; set; }
        public string publisher { get; set; }
        public string source { get; set; }
        public string releaseinfo { get; set; }
        public string version { get; set; }

        public Header(XNamespace ns, XNamespace nsDc, XElement benchmark)
        {
            status = (string)benchmark.Element(ns + "status");
            date = (DateTime)benchmark.Element(ns + "status").Attribute("date");
            title = (string)benchmark.Element(ns + "title");
            description = (string)benchmark.Element(ns + "description");
            notice = (string)benchmark.Element(ns + "notice");
            publisher = (string)benchmark.Descendants(nsDc + "publisher").FirstOrDefault();
            source = (string)benchmark.Descendants(nsDc + "source").FirstOrDefault();
            releaseinfo = (string)benchmark.Element(ns + "plain-text");
            version = (string)benchmark.Element(ns + "version");
        }
    }
    public class Profiles
    {
        public static List<Profiles> ProfileList { get; set; }
        public string id { get; set; }
        public string title { get; set; }
        public string description { get; set; }
        public List<Profile> profiles { get; set; }

        public Profiles() { }
        public Profiles(XNamespace ns, XElement benchmark)
        {
            List<XElement> xProfiles = benchmark.Elements(ns + "Profile").ToList();
            ProfileList = new List<Profiles>();
            foreach (XElement xProfile in xProfiles)
            {
                Profiles Profile = new Profiles();
                ProfileList.Add(Profile);
                Profile.id = (string)xProfile.Attribute("id");
                Profile.title = (string)xProfile.Element(ns + "title");
                Profile.description = (string)xProfile.Element(ns + "description");
                Profile.profiles = xProfile.Elements(ns + "select").Select(x => new Profile()
                {
                    idref = (string)x.Attribute("idref"),
                    selected = (Boolean)x.Attribute("selected")
                }).ToList();
            }
        }

    }
    public class Profile
    {
        public string idref { get; set; }
        public Boolean selected { get; set; }
    }
    public class Group
    {
        public static List<Group> GroupList { get; set; }
        public string id { get; set; }
        public string title { get; set; }
        public string description { get; set; }
        public Rule rule { get; set; }

        public Group() { }
        public Group(XNamespace ns, XNamespace nsDc, XElement benchmark)
        {
            List<XElement> xGroups = benchmark.Elements(ns + "Group").ToList();
            GroupList = new List<Group>();
            foreach (XElement xGroup in xGroups)
            {
                Group group = new Group();
                GroupList.Add(group);
                group.id = (string)xGroup.Attribute("id");
                group.title = (string)xGroup.Element(ns + "title");
                group.description = (string)xGroup.Element(ns + "description");
                XElement xRule = xGroup.Element(ns + "Rule");
                group.rule = new Rule();
                group.rule.id = (string)xRule.Attribute("id");
                group.rule.severity = (string)xRule.Attribute("severity");
                group.rule.weight = (decimal)xRule.Attribute("weight");
                group.rule.version = (string)xRule.Element(ns + "version");
                group.rule.title = (string)xRule.Element(ns + "title");
                group.rule.description = (string)xRule.Element(ns + "description");


                group.rule.idents = xRule.Elements(ns + "idents").Select(x => (string)x).ToList();
                group.rule.fixtext = (string)xRule.Element(ns + "fixtext");
                group.rule.fixref = (string)xRule.Element(ns + "fixtext").Attribute("fixref");
                group.rule.fix = (string)xRule.Element(ns + "fix").Attribute("id");

                XElement xReference = xRule.Element(ns + "reference");
                group.rule.reference = new Reference();
                group.rule.reference.title = (string)xReference.Element(nsDc + "title");
                group.rule.reference.publisher = (string)xReference.Element(nsDc + "publisher");
                group.rule.reference.type = (string)xReference.Element(nsDc + "type");
                group.rule.reference.subject = (string)xReference.Element(nsDc + "subject");
                group.rule.reference.identifier = (string)xReference.Element(nsDc + "identifier"); 


            }
        }
    }
    public class Rule
    {
        public string id { get; set; }
        public string severity { get; set; }
        public decimal weight { get; set; }
        public string version { get; set; }
        public string title { get; set; }
        public string description { get; set; }
        public List<string> idents { get; set; }
        public string fixref { get; set; }
        public string fixtext { get; set; }
        public string fix { get; set; }
        public Reference reference { get; set; }

    }
    public class Reference
    {
        public string title { get; set; }
        public string publisher { get; set; }
        public string type { get; set; }
        public string subject { get; set; }
        public string identifier { get; set; }
    }
}

【讨论】:

  • +1 用于展示您的方法。这适用于所有修订版吗?我不确定 xml 的格式在修订之间有多少变化(内容确定)。我想创建一个应用程序,我可以在其中将我自己的 cmets 添加到每个 STIG 并为每个新版本维护它们。
  • 有一个模式可用于创建 c# 类。当架构更改时,我的代码可能无法正常工作。有像 xsd.exe 这样的工具会自动获取架构并创建类。但是使用该工具将创建更多的类层。我只有 6 节课。
  • 我现在正在尝试这种方法,我可以在&lt;Group&gt; tag 中读取id,但&lt;title&gt;&lt;description&gt; 显示为空。您是否正确阅读了代码中的所有这些字段?谢谢!
  • 数据在类的静态成员中。所以你不要使用类的实例来访问。使用 Group.GroupList 和 Profiles,ProfileList
  • "ns" 在两个语句中丢失: group.title = (string)xGroup.Element(ns + "title"); group.description = (string)xGroup.Element(ns + "description");
【解决方案2】:

啊,光荣的 STIG。但你的问题是它是如何做到的?格式良好的 XML 是可解析的,以及为什么他们可以在 XML 中释放 15000 多行这样的行以供解析和使用。

只要它是线性的或锯齿状的,它就是线性的,这意味着它将按照你的方式从头到尾处理它。如果该 XML 文件有/有 1 个无效部分,则它将无法读取。您可以通过在某处删除标签来测试这一点。它应该抛出一个异常。

如果您正在寻找一种不将其全部加载到内存中的方法,考虑到大小,请查看这个 SO 答案:Loading large XML on DataSet (OutOfMemory Exception)。如果这不是您提出问题的原因,请告诉我们,我们可以看看我们是否能弄清楚您的目标。

【讨论】:

  • 好吧,我试图从整体上理解它,比如为什么它报告 3 列 plaint-text DataTable,列 id、plain-text_Text 和 Benchmark_Id。最后一个不在节点中。我的确切问题是DataSet.Tables 列表之间没有关系,所以它如何能够将所有累积的 DataTables 放在一个线性列表中,但它们却正确地再现了 xml 文件。另外我想检查一下某某的父母是不是这个!
  • @zar,我明天看看能不能给你写一个更完整的答案。我还会将其添加为对您原始问题的修改,以防其他人可能会为您提供答案。
  • 当然我更新了问题以使其清楚。
猜你喜欢
  • 2013-05-27
  • 2017-05-26
  • 1970-01-01
  • 2013-09-23
  • 1970-01-01
  • 2018-01-08
  • 1970-01-01
  • 2010-09-11
  • 1970-01-01
相关资源
最近更新 更多