【问题标题】:Check if XML node exists - Loop not finding node if its available检查 XML 节点是否存在 - 如果节点可用,则循环未找到节点
【发布时间】:2017-07-12 14:24:30
【问题描述】:

我有一个 XML 文件,其中一些记录缺少某些节点/元素(导入表所需的信息)。如果该记录缺少某个节点,那么我设置一个默认值并继续下一条记录。在示例 XML 文件中,产品 A 没有 Barcode 节点,因此根据其他信息生成该值,产品 B 具有所需的所有节点,因此所有值都取自节点。

<ProdExtract>
<Product>
    <BasicFields>
        <ProductCode>000011</ProductCode>
        <LongDescription>Product A</LongDescription>
    </BasicFields>
</Product>

<Product>
    <BasicFields>
        <ProductCode>000012</ProductCode>
        <LongDescription>Product B</LongDescription>
    </BasicFields>
    <Barcode>         
      <Eancode>5391524344444</Eancode>        
    </Barcode>
</Product>
</ProdExtract>

我的 C# 代码如下。

foreach (XmlNode node in nodes)                        
{
   XmlNodeList barcodeExists = xDoc.GetElementsByTagName("Product/Barcode");

   if (barcodeExists.Count > 0)
   {
      /*get the inner text of that node*/
      p.q_barcode = node.SelectSingleNode("Barcode/Eancode").FirstChild.InnerText;
   }
   else
   {
      /* ---
      If product has no Barcode node,
      Lets set our default value for products without that node
      --- */        
   }
}

现在,当检查通过第一条没有条形码节点的记录时,它将转到else 语句并运行生成值所需的代码并完美地插入第一条记录。在第二次检查所有节点的记录时,它仍然以某种方式跳转到else 并在它应该简单地从“条形码/Eancode”的if 内部文本中获取值时生成一个值。即使交换记录并将产品 B 放在首位,仍然会出现同样的问题。

我什至尝试了以下方法,但仍然没有为产品 B 获得适当的价值

var barcodeExists = node.SelectSingleNode("Product/Barcode");

if (barcodeExists != null)
{
   /*Barcode node exists, get the value from that node*/
   p.q_barcode = node.SelectSingleNode("Barcode/Eancode").FirstChild.InnerText;
}

【问题讨论】:

  • xDoc.GetElementsByTagName("Product/Barcode") 不会总是看first &lt;Product&gt;(按文档顺序)吗?您不应该使用node.SelectSingleNode("Barcode") 之类的东西来查找当前node 的特定&lt;Barcode&gt; inside 吗? -- 另外,您可能想看看LINQ to XML,它提供了一种更好的方式来处理 XML 数据。
  • var barcodeExists = node.SelectSingleNode("Product/Barcode"); 看起来几乎正确,但 node 已经代表 &lt;Product&gt;,因此寻找 "Product/Barcode" 将搜索 &lt;Product&gt; inside &lt;Product&gt; .只需从您要查找的路径中删除 Product 部分,它可能会起作用。所以它会是:var barcodeExists = node.SelectSingleNode("Barcode");
  • @Corak 我以前有node.SelectSingleNode("Product/Barcode") 仍然给我同样的问题,并在您输入时将其更改为node.SelectSingleNode("Barcode") 修复了问题。它总是小事。谢谢

标签: c# xml


【解决方案1】:

要获取节点列表,只需将节点名称传递给方法GetElementsByTagName

var node = xmlDoc.GetElementsByTagName("Barcode");

附件是显示它在 Visual Studio 调试器中的价值的屏幕截图

另外,添加您的 Xml 也不完全正确。

我已将其更改为正确的 Xml。我使用的样本是

<ProdExtract>
    <Product>
        <BasicFields>
            <ProductCode>000011</ProductCode>
            <LongDescription>Product A</LongDescription>
        </BasicFields>
    </Product>

    <Product>
        <BasicFields>
            <ProductCode>000012</ProductCode>
            <LongDescription>Product B</LongDescription>
        </BasicFields>
        <Barcode>         
            <Eancode>5391524344444</Eancode>        
        </Barcode>
    </Product>
</ProdExtract>

您可以像这样解析您的 Xml:

        var nodeList = xmlDoc.GetElementsByTagName("Barcode");

        if (nodeList != null)
        {
            if (nodeList.Count > 0)
            {
                var element = nodeList[0];

                string value = element.InnerText;
            }
        }

基于Xml构造对象的完整方法

此方法中的逻辑是导航 Xml 并选择所需的值并将其设置为对象。

    private static Product[] GetDetails(XmlDocument xmlDoc)
    {
        var result = new List<Product>();
        XmlNode tempNode;

        var nodeList = xmlDoc.GetElementsByTagName("Product");

        foreach(XmlNode node in nodeList)
        {
            var product = new Product();

            tempNode = node.FirstChild; //BasicFields

            if (tempNode != null)
            {
                product.ProductCode = tempNode["ProductCode"].InnerText;
                product.LongDescription = tempNode["LongDescription"].InnerText;
            }

            if (node.ChildNodes.Count > 1)
            {
                tempNode = node.ChildNodes[1];

                if (tempNode != null)
                {
                    tempNode = tempNode.FirstChild; //Eancode
                    if (tempNode != null)
                    {
                        product.Barcode = tempNode.InnerText;
                    }
                }
            }

            result.Add(product);
        }

        return result.ToArray();
    }

在上面的例子中,Product 是一个简单的类来保存数据

class Product
{
    public string ProductCode { get; set; }
    public string LongDescription { get; set; }
    public string Barcode { get; set; }
}

【讨论】:

  • 感谢@Subbu 的详细回答,问题在于("Product/Barcode") 而不是("Barcode")。只是好奇,我发布的 XML 有什么不完全正确的地方?
  • Xml 中的小问题,第 6 行,应该是 /BasicFields,同样在第 13 行中
  • 啊,是的,我现在看到了。我在这里粘贴代码时犯了一个错字/错误。我只是想知道,因为我使用的文件没有给我任何问题。感谢您指出这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-04
  • 2011-04-16
相关资源
最近更新 更多