简体   繁体   中英

Issue with adding a new node in XML

I am trying to add a new node in my XML file, but I get InvalidOperationException due to the current position of the navigator.

This is my XML file:

<?xml version="1.0" encoding="utf-8" ?> 
<dictionary xmlns="RecnikSema.xsd">

<sentiments>

  <sentiment word="napustiti">-2</sentiment>

</sentiments>  

</dictionary>

and schema:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="dictionary">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="sentiments">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="sentiment">
                <xs:complexType>
                  <xs:simpleContent>
                    <xs:extension base="xs:string">
                      <xs:attribute type="xs:string" name="word"/>
                      <xs:attribute type="xs:double" name="value"/>
                    </xs:extension>
                  </xs:simpleContent>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

The code in C# which I am using to add a new node looks like this:

XmlDocument dictionary= new XmlDocument();
dictionary.Load(@"C:\Users\Luka\Documents\Visual Studio 2013\Projects\TSA\TSA\Dictionary.xml");
XPathNavigator navigator = dictionary.CreateNavigator();

navigator.MoveToChild("dictionary", @"C:\Users\Luka\Documents\Visual Studio 2013\Projects\TSA\TSA\RecnikSema.xsd");
navigator.MoveToChild("sentiments", @"C:\Users\Luka\Documents\Visual Studio 2013\Projects\TSA\TSA\RecnikSema.xsd");
navigator.MoveToChild("sentiment", @"C:\Users\Luka\Documents\Visual Studio 2013\Projects\TSA\TSA\RecnikSema.xsd");

navigator.InsertAfter("<sentiment word=\"" + token + "\">" + value + "</sentiment>");

The exception is occuring on the last line, on InsertAfter .

What am I doing wrong here?

In MoveToChild() , the second argument is the XML namespace, not the location of your document. In your case, you have set xmlns="RecnikSema.xsd" . This means MoveToChild cannot find a match, so when you get to insertAfter , the current node is still the root node <dictionary> , and it attempts to create XML like this:

<?xml version="1.0" encoding="utf-8" ?> 
<dictionary xmlns="RecnikSema.xsd">
    <sentiment word="napustiti">-2</sentiment>
</dictionary>
<sentiment word="foo">5</sentiment>

This has 2 root elements and so you get the error

Instead you need to pass "RecnikSema.xsd" as the argument.:

navigator.MoveToChild("dictionary", "RecnikSema.xsd");
navigator.MoveToChild("sentiments", "RecnikSema.xsd");
navigator.MoveToChild("sentiment", "RecnikSema.xsd");

I'm not sure you meant to set this as the namespace as it is the Schema file, so maybe you mean this?:

XML

<?xml version="1.0" encoding="utf-8" ?> 
<dictionary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="RecnikSema.xsd">
    <sentiments>
        <sentiment word="napustiti">-2</sentiment>
    </sentiments>
</dictionary>

C#

XmlDocument dictionary= new XmlDocument();
dictionary.Load(@"C:\Users\Luka\Documents\Visual Studio 2013\Projects\TSA\TSA\Dictionary.xml");
XPathNavigator navigator = dictionary.CreateNavigator();

navigator.MoveToChild("dictionary", "");
navigator.MoveToChild("sentiments", "");
navigator.MoveToChild("sentiment", "");

navigator.InsertAfter("<sentiment word=\"" + token + "\">" + value + "</sentiment>");

I think your problem is that you did not specify the maxOccurs (default is 1) and you allready added on element. See http://www.w3schools.com/schema/el_sequence.asp

maxOccurs Optional. Specifies the maximum number of times the sequence element can occur in the parent element. The value can be any number>= 0, or if you want to set no limit on the maximum number, use the value "unbounded". Default value is 1

so your Solution for multiple sentiments:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="dictionary">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="sentiments">
          <xs:complexType>
            <xs:sequence maxOccurs="unbounded">
              <xs:element name="sentiment">
                <xs:complexType>
                  <xs:simpleContent>
                    <xs:extension base="xs:string">
                      <xs:attribute type="xs:string" name="word"/>
                      <xs:attribute type="xs:double" name="value"/>
                    </xs:extension>
                  </xs:simpleContent>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

I would prefer using Microsoft xsd tool to generate a CLR Class -> http://msdn.microsoft.com/en-us/library/x6c1kb0s(v=vs.110).aspx and using XMLSerializer -> http://msdn.microsoft.com/de-de/library/system.xml.serialization.xmlserializer(v=vs.110).aspx

Why don't you make it simple mate by using XDocument.

The new version of C# has got this class that makes it easy to manipulate Xml. Thus, it also supports Xml Linq as well.

Here is the quick solution that may be useful for you.

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            XDocument document = XDocument.Load(@"C:\Users\amit\SkyDrive\code\WebApplication1\ConsoleApplication1\xml.xml");
            XElement root = new XElement("sentiment");
            root.Value = "3";
            root.Add(new XAttribute("word", "napustiti"));
            XNamespace nsSys = "RecnikSema.xsd";
            document.Element(nsSys + "dictionary").Element(nsSys + "sentiments").Add(root);
            document.Save("c:\newFile.xml");
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM