【问题标题】:Linq XML NullReference Exception on reading list of elements阅读元素列表时出现 Linq XML NullReference 异常
【发布时间】:2016-11-11 18:12:03
【问题描述】:

我正在尝试从我的 Xml 文件中读取文本节点列表。当我尝试读取列出的 1 个文本元素的子节点时,我得到 NullReference 异常,即使 XDocument 节点看似已填充。 NullReference 异常在foreach (XElement textElement in textElements) 行上引发,这意味着列表 textElements 的 Count > 1 所以它不应该为空。这是调试器愿意做的。

我是在以错误的方式阅读 Xml,还是不允许/不应该像现在这样构建 XElement 列表?

这是我的 XML 文件

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Book SYSTEM "Book.dtd"[]>
<album version="0.2" settingsVersion="1">
  <size />
  <cover />
  <inner>
    <page>
      <pagenumber>1</pagenumber>
      <image>1.jpg</image>
      <text>
        <value>Test </value>
        <font>arial</font>
        <size>18pt</size>
        <style>normal</style>
        <weight>normal</weight>
        <color>#77DD44</color>
        <rotation>0</rotation>
        <alignment>start</alignment>
        <position>
          <x>50</x>
          <y>50</y>
        </position>
      </text>
      <text>
          <value>Test 2 </value>
          <font>arial</font>
          <size>18pt</size>
          <style>normal</style>
          <weight>normal</weight>
          <color>#77DD44</color>
          <rotation>0</rotation>
          <alignment>start</alignment>
          <position>
             <x>50</x>
             <y>50</y>
          </position>
       </text>
    </page>
  </inner>
</album>

元素inner可以容纳多个page元素,page可以容纳多个text元素。

我通过以下方法读取了 Xml。

List<XElement> pageElements = doc.Root.Element("inner").Elements("page").ToList();
foreach (XElement pageElement in pageElements)
{
    string pageNumberString = pageElement.Element("pagenumber").Value;
    int pageNumberValue = Convert.ToInt32(pageNumberString);
    string fileNameValue = pageElement.Element("image").Value;
    // Verify if the currently looped page is the same as the one selected by the user.
    if (pageNumberValue == pageNumber)
    {
        // Get all text nodes from the found page.
        List<XElement> textElements = pageElement.Elements("text").ToList();
        // If no text nodes found return the page with an empty TextInfo array.
        if (textElements.Count == 0)
        {
            PageInfo pageInfoNoText = new PageInfo { PageNumber = pageNumberValue, FileName = fileNameValue, Text = new TextInfo[0] };
            Logger.log("PageInfo found for collection {0}. Info {1}", collectionId, pageInfoNoText);
            return pageInfoNoText;
        }
        // If text nodes are found build a list of TextInfo objects and build a new PageInfo object.
        else
        {
            // All text elements in the XML under the found page.
            List<TextInfo> textInfoList = new List<TextInfo>();
            TextInfo[] textArray = new TextInfo[0];

            #region  Load all required text data from the XML file and build the textList.
            foreach (XElement textElement in textElements)
            {
                string textValue = textElement.Element("value").Value;

                string fontValue = textElement.Element("font").Value;

                string fontSizeValue = textElement.Element("size").Value;

                string styleValue = textElement.Element("style").Value;

                string weightValue = textElement.Element("weight").Value;

                string colorValue = textElement.Element("color").Value;

                string rotationString = textElement.Element("rotation").Value;
                int rotationValue = Convert.ToInt32(rotationString);

                string alignmentValue = textElement.Element("alignment").Value;

                string positionXString = textElement.Element("x").Value;
                int positionXValue = Convert.ToInt32(positionXString);

                string positionYString = textElement.Element("y").Value;
                int positionYValue = Convert.ToInt32(positionYString);

                // Build Info objects.
                PositionInfo tempPositionInfo = new PositionInfo
                {
                    X = positionXValue,
                    Y = positionYValue
                };

                TextInfo tempTextInfo = new TextInfo
                {
                    Value = textValue,
                    Font = fontValue,
                    Size = fontSizeValue,
                    Style = styleValue,
                    Weight = weightValue,
                    Color = colorValue,
                    Rotation = rotationValue,
                    Alignment = alignmentValue,
                    Position = tempPositionInfo
                };

                textInfoList.Add(tempTextInfo);

            }
            textArray = textInfoList.ToArray();
            #endregion

            PageInfo pageInfo = new PageInfo
            {
                PageNumber = pageNumberValue,
                FileName = fileNameValue,
                Text = textArray
            };
            Logger.log("PageInfo found for collection {0}. Info: {1}", collectionId, pageInfo);
            return pageInfo;

        }
    }
}

感谢任何帮助/见解!

【问题讨论】:

    标签: c# xml linq


    【解决方案1】:

    您的代码很好,但是当您获取 x 和 y 值时出现错误,您需要获取 position 元素的 x 和 y 值,如下所示

    string positionXString = (string)textElement.Element("position").Element("x").Value;
    int positionXValue = Convert.ToInt32(positionXString);
    string positionYString = (string)textElement.Element("position").Element("y").Value;
    int positionYValue = Convert.ToInt32(positionYString);
    

    【讨论】:

    • 刚刚也发现了这一点。键入此主题有助于让我摆脱代码并重置。尽管如此,还是感谢您的快速评论!
    【解决方案2】:

    您的文本元素不包含名为 x 的元素,因此尝试访问 x 的值会导致 NullReferenceException:

    string positionXString = textElement.Element("x").Value;
    // textElement.Element("x") is null, "x" is in textElement.Element("position")
    int positionXValue = Convert.ToInt32(positionXString);
    

    为此,您可能会更好地使用 Descendants (Descendants("x").FirstOrDefault()?.Value) 而不是 Element,但总体而言,您可能希望完全重组它。

    【讨论】:

    • 是的,我也发现了它。键入此主题有助于让我摆脱代码并重置。尽管如此,还是感谢您的快速评论!
    猜你喜欢
    • 2016-01-11
    • 1970-01-01
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    • 1970-01-01
    相关资源
    最近更新 更多