Partilhar via


Modificar dados XML usando XPathNavigator

A XPathNavigator classe fornece um conjunto de métodos usados para modificar nós e valores em um documento XML. Para usar esses métodos, o XPathNavigator objeto deve ser editável, ou seja, sua CanEdit propriedade deve ser true.

XPathNavigator objetos que podem editar um documento XML são criados pelo CreateNavigator método da XmlDocument classe. XPathNavigator Os objetos criados pela XPathDocument classe são somente leitura e qualquer tentativa de usar os métodos de edição de um XPathNavigator objeto criado por um XPathDocument objeto resulta em um NotSupportedExceptionarquivo .

Para obter mais informações sobre como criar objetos editáveis XPathNavigator , consulte Lendo dados XML usando XPathDocument e XmlDocument.

Modificando nós

Uma técnica simples para alterar o valor de um nó é usar os SetValue métodos e SetTypedValue da XPathNavigator classe.

A tabela a seguir lista os efeitos desses métodos em diferentes tipos de nós.

XPathNodeType Dados alterados
Root Não suportado.
Element O conteúdo do elemento.
Attribute O valor do atributo.
Text O conteúdo do texto.
ProcessingInstruction O conteúdo, excluindo o alvo.
Comment O conteúdo do comentário.
Namespace Não suportado.

Nota

Não há suporte para a edição Namespace de nós ou do Root nó.

A XPathNavigator classe também fornece um conjunto de métodos usados para inserir e remover nós. Para obter mais informações sobre como inserir e remover nós de um documento XML, consulte os tópicos Inserir dados XML usando XPathNavigator e Remover dados XML usando XPathNavigator .

Modificando valores não tipados

O SetValue método simplesmente insere o valor não tipado string passado como um parâmetro como o valor do nó no qual o XPathNavigator objeto está posicionado no momento. O valor é inserido sem qualquer tipo ou sem verificar se o novo valor é válido de acordo com o tipo do nó se as informações do esquema estiverem disponíveis.

No exemplo a seguir, o SetValue método é usado para atualizar todos os price elementos no contosoBooks.xml arquivo.

XmlDocument^ document = gcnew XmlDocument();
document->Load("contosoBooks.xml");
XPathNavigator^ navigator = document->CreateNavigator();

XmlNamespaceManager^ manager = gcnew XmlNamespaceManager(navigator->NameTable);
manager->AddNamespace("bk", "http://www.contoso.com/books");

for each (XPathNavigator^ nav in navigator->Select("//bk:price", manager))
{
    if(nav->Value == "11.99")
    {
        nav->SetValue("12.99");
    }
}

Console::WriteLine(navigator->OuterXml);
XmlDocument document = new XmlDocument();
document.Load("contosoBooks.xml");
XPathNavigator navigator = document.CreateNavigator();

XmlNamespaceManager manager = new XmlNamespaceManager(navigator.NameTable);
manager.AddNamespace("bk", "http://www.contoso.com/books");

foreach (XPathNavigator nav in navigator.Select("//bk:price", manager))
{
    if (nav.Value == "11.99")
    {
        nav.SetValue("12.99");
    }
}

Console.WriteLine(navigator.OuterXml);
Dim document As XmlDocument = New XmlDocument()
document.Load("contosoBooks.xml")
Dim navigator As XPathNavigator = document.CreateNavigator()

Dim manager As XmlNamespaceManager = New XmlNamespaceManager(navigator.NameTable)
manager.AddNamespace("bk", "http://www.contoso.com/books")

For Each nav As XPathNavigator In navigator.Select("//bk:price", manager)
    If nav.Value = "11.99" Then
        nav.SetValue("12.99")
    End If
Next

Console.WriteLine(navigator.OuterXml)

O exemplo usa o contosoBooks.xml arquivo como uma entrada.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
    <book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
        <title>The Autobiography of Benjamin Franklin</title>
        <author>
            <first-name>Benjamin</first-name>
            <last-name>Franklin</last-name>
        </author>
        <price>8.99</price>
    </book>
    <book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
        <title>The Confidence Man</title>
        <author>
            <first-name>Herman</first-name>
            <last-name>Melville</last-name>
        </author>
        <price>11.99</price>
    </book>
    <book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
        <title>The Gorgias</title>
        <author>
            <name>Plato</name>
        </author>
        <price>9.99</price>
    </book>
</bookstore>

Modificando valores digitados

Quando o tipo de um nó é um tipo simples de esquema XML W3C, o novo valor inserido pelo método é verificado em relação às SetTypedValue facetas do tipo simples antes que o valor seja definido. Se o novo valor não for válido de acordo com o tipo do nó (por exemplo, definindo um valor de -1 em um elemento cujo tipo é xs:positiveInteger), isso resultará em uma exceção.

O exemplo a seguir tenta alterar o price valor do elemento do primeiro book elemento no contosoBooks.xml arquivo para um DateTime valor. Como o tipo de esquema XML do price elemento é definido como xs:decimal nos contosoBooks.xsd arquivos, isso resulta em uma exceção.

Dim settings As XmlReaderSettings = New XmlReaderSettings()  
settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd")  
settings.ValidationType = ValidationType.Schema  
  
Dim reader As XmlReader = XmlReader.Create("contosoBooks.xml", settings)  
  
Dim document As XmlDocument = New XmlDocument()  
document.Load(reader)  
Dim navigator As XPathNavigator = document.CreateNavigator()  
  
navigator.MoveToChild("bookstore", "http://www.contoso.com/books")  
navigator.MoveToChild("book", "http://www.contoso.com/books")  
navigator.MoveToChild("price", "http://www.contoso.com/books")  
  
navigator.SetTypedValue(DateTime.Now)  
XmlReaderSettings settings = new XmlReaderSettings();  
settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");  
settings.ValidationType = ValidationType.Schema;  
  
XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);  
  
XmlDocument document = new XmlDocument();  
document.Load(reader);  
XPathNavigator navigator = document.CreateNavigator();  
  
navigator.MoveToChild("bookstore", "http://www.contoso.com/books");  
navigator.MoveToChild("book", "http://www.contoso.com/books");  
navigator.MoveToChild("price", "http://www.contoso.com/books");  
  
navigator.SetTypedValue(DateTime.Now);  

O exemplo usa o contosoBooks.xml arquivo como uma entrada.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
    <book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
        <title>The Autobiography of Benjamin Franklin</title>
        <author>
            <first-name>Benjamin</first-name>
            <last-name>Franklin</last-name>
        </author>
        <price>8.99</price>
    </book>
    <book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
        <title>The Confidence Man</title>
        <author>
            <first-name>Herman</first-name>
            <last-name>Melville</last-name>
        </author>
        <price>11.99</price>
    </book>
    <book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
        <title>The Gorgias</title>
        <author>
            <name>Plato</name>
        </author>
        <price>9.99</price>
    </book>
</bookstore>

O exemplo também toma o contosoBooks.xsd como uma entrada.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.contoso.com/books" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="bookstore">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" name="book">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="title" type="xs:string" />
                            <xs:element name="author">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element minOccurs="0" name="name" type="xs:string" />
                                        <xs:element minOccurs="0" name="first-name" type="xs:string" />
                                        <xs:element minOccurs="0" name="last-name" type="xs:string" />
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                            <xs:element name="price" type="xs:decimal" />
                        </xs:sequence>
                        <xs:attribute name="genre" type="xs:string" use="required" />
                        <xs:attribute name="publicationdate" type="xs:date" use="required" />
                        <xs:attribute name="ISBN" type="xs:string" use="required" />
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Os efeitos da edição de dados XML fortemente tipados

A XPathNavigator classe usa o esquema XML W3C como base para descrever XML fortemente tipado. Elementos e atributos podem ser anotados com informações de tipo com base na validação em relação a um documento do esquema XML W3C. Os elementos que podem conter outros elementos ou atributos são chamados de tipos complexos, enquanto aqueles que só podem conter conteúdo textual são chamados de tipos simples.

Nota

Os atributos só podem ter tipos simples.

Um elemento ou atributo pode ser considerado válido de esquema se estiver em conformidade com todas as regras específicas de sua definição de tipo. Um elemento que tem o tipo xs:int simples deve conter um valor numérico entre -2147483648 e 2147483647 para ser esquema-válido. Para tipos complexos, a validade de esquema do elemento depende da validade de esquema de seus elementos e atributos filho. Assim, se um elemento é válido em relação à sua definição de tipo complexa, todos os seus elementos e atributos filho são válidos em relação às suas definições de tipo. Da mesma forma, se até mesmo um dos elementos filho ou atributos de um elemento é inválido em relação à sua definição de tipo, ou tem uma validade desconhecida, o elemento também é inválido ou de validade desconhecida.

Dado que a validade de um elemento depende da validade de seus elementos e atributos filho, modificações em ambos resultam na alteração da validade do elemento se ele era válido anteriormente. Especificamente, se os elementos filho ou atributos de um elemento forem inseridos, atualizados ou excluídos, a validade do elemento se tornará desconhecida. Isso é representado pela Validity propriedade da propriedade do elemento que SchemaInfo está sendo definida como NotKnown. Além disso, esse efeito cascata para cima recursivamente através do documento XML, porque a validade do elemento pai do elemento (e seu elemento pai, e assim por diante) também se torna desconhecida.

Para obter mais informações sobre a validação de esquema e a XPathNavigator classe, consulte Validação de esquema usando XPathNavigator.

Modificando atributos

Os SetValue métodos e SetTypedValue podem ser usados para modificar nós de atributo não tipados e digitados, bem como os outros tipos de nó listados na seção "Modificando nós".

O exemplo a books.xml seguir altera o valor do genre atributo do primeiro book elemento no arquivo.

Dim document As XmlDocument = New XmlDocument()  
document.Load("books.xml")  
Dim navigator As XPathNavigator = document.CreateNavigator()  
  
navigator.MoveToChild("bookstore", String.Empty)  
navigator.MoveToChild("book", String.Empty)  
navigator.MoveToAttribute("genre", String.Empty)  
  
navigator.SetValue("non-fiction")  
  
navigator.MoveToRoot()  
Console.WriteLine(navigator.OuterXml)  
XmlDocument document = new XmlDocument();  
document.Load("books.xml");  
XPathNavigator navigator = document.CreateNavigator();  
  
navigator.MoveToChild("bookstore", String.Empty);  
navigator.MoveToChild("book", String.Empty);  
navigator.MoveToAttribute("genre", String.Empty);  
  
navigator.SetValue("non-fiction");  
  
navigator.MoveToRoot();  
Console.WriteLine(navigator.OuterXml);  

Para obter mais informações sobre os SetValue métodos and SetTypedValue , consulte as seções "Modificando valores não tipados" e "Modificando valores digitados".

Propriedades InnerXml e OuterXml

As InnerXml propriedades e OuterXml da classe alteram XPathNavigator a marcação XML dos nós nos quais um XPathNavigator objeto está posicionado no momento.

A InnerXml propriedade altera a marcação XML dos nós filho em que um XPathNavigator objeto está posicionado atualmente com o conteúdo analisado do XML stringfornecido. Da mesma forma, a OuterXml propriedade altera a marcação XML dos nós filho nos quais um XPathNavigator objeto está posicionado no momento, bem como o próprio nó atual.

O exemplo a seguir usa a OuterXml propriedade para modificar o valor do price elemento e inserir um novo discount atributo no primeiro book elemento do contosoBooks.xml arquivo.

Dim document As XmlDocument = New XmlDocument()  
document.Load("contosoBooks.xml");  
Dim navigator As XPathNavigator = document.CreateNavigator()  
  
navigator.MoveToChild("bookstore", "http://www.contoso.com/books")  
navigator.MoveToChild("book", "http://www.contoso.com/books")  
navigator.MoveToChild("price", "http://www.contoso.com/books")  
  
navigator.OuterXml = "<price discount=\"0\">10.99</price>"  
  
navigator.MoveToRoot()  
Console.WriteLine(navigator.OuterXml)  
XmlDocument document = new XmlDocument();  
document.Load("contosoBooks.xml");  
XPathNavigator navigator = document.CreateNavigator();  
  
navigator.MoveToChild("bookstore", "http://www.contoso.com/books");  
navigator.MoveToChild("book", "http://www.contoso.com/books");  
navigator.MoveToChild("price", "http://www.contoso.com/books");  
  
navigator.OuterXml = "<price discount=\"0\">10.99</price>";  
  
navigator.MoveToRoot();  
Console.WriteLine(navigator.OuterXml);  

O exemplo usa o contosoBooks.xml arquivo como uma entrada.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
    <book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
        <title>The Autobiography of Benjamin Franklin</title>
        <author>
            <first-name>Benjamin</first-name>
            <last-name>Franklin</last-name>
        </author>
        <price>8.99</price>
    </book>
    <book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
        <title>The Confidence Man</title>
        <author>
            <first-name>Herman</first-name>
            <last-name>Melville</last-name>
        </author>
        <price>11.99</price>
    </book>
    <book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
        <title>The Gorgias</title>
        <author>
            <name>Plato</name>
        </author>
        <price>9.99</price>
    </book>
</bookstore>

Modificando nós de namespace

No DOM (Document Object Model), as declarações de namespace são tratadas como se fossem atributos regulares que podem ser inseridos, atualizados e excluídos. A XPathNavigator classe não permite tais operações em nós de namespace porque alterar o valor de um nó de namespace pode alterar a identidade dos elementos e atributos dentro do escopo do nó de namespace, conforme ilustrado no exemplo a seguir.

<root xmlns="http://www.contoso.com">  
    <child />  
</root>  

Se o exemplo XML acima for alterado da seguinte maneira, isso efetivamente renomeará todos os elementos no documento porque o valor do URI de namespace de cada elemento será alterado.

<root xmlns="urn:contoso.com">  
    <child />  
</root>  

A inserção de nós de namespace que não entram em conflito com declarações de namespace no escopo em que eles estão inseridos XPathNavigator é permitida pela classe. Nesse caso, as declarações de namespace não são declaradas em escopos mais baixos no documento XML e não resultam em renomeação, conforme ilustrado no exemplo a seguir.

<root xmlns:a="http://www.contoso.com">  
    <parent>  
        <a:child />  
    </parent>  
</root>  

Se o exemplo XML acima for alterado da seguinte maneira, as declarações de namespace serão propagadas corretamente pelo documento XML abaixo do escopo da outra declaração de namespace.

<root xmlns:a="http://www.contoso.com">  
    <parent a:parent-id="1234" xmlns:a="http://www.contoso.com/parent-id">  
        <a:child xmlns:a="http://www.contoso.com/" />  
    </parent>  
</root>  

No exemplo XML acima, o atributo a:parent-id é inserido parent no elemento no http://www.contoso.com/parent-id namespace. O CreateAttribute método é usado para inserir o atributo enquanto posicionado parent no elemento . A http://www.contoso.com declaração de namespace é inserida XPathNavigator automaticamente pela classe para preservar a consistência do restante do documento XML.

Modificando nós de referência de entidade

Os nós de referência de entidade em um XmlDocument objeto são somente leitura e não podem ser editados usando as XPathNavigator classes or XmlNode . Qualquer tentativa de modificar um nó de referência de entidade resulta em um InvalidOperationExceptionarquivo .

Modificando nós xsi:nil

A recomendação do esquema XML do W3C introduz o conceito de um elemento ser nillable. Quando um elemento é nillable, é possível que o elemento não tenha conteúdo e ainda seja válido. O conceito de um elemento ser nulo é semelhante ao conceito de um objeto ser null. A principal diferença é que um null objeto não pode ser acessado de forma alguma, enquanto um xsi:nil elemento ainda tem propriedades como atributos que podem ser acessados, mas não tem conteúdo (elementos filho ou texto). A existência do xsi:nil atributo com um valor de true on um elemento em um documento XML é usada para indicar que um elemento não tem conteúdo.

Se um XPathNavigator objeto for usado para adicionar conteúdo a um elemento válido com um xsi:nil atributo com um valor de true, o valor de seu xsi:nil atributo será definido como false.

Nota

Se o conteúdo de um elemento com um xsi:nil atributo definido como false for excluído, o valor do atributo não será alterado para true.

Guardar um documento XML

Salvar alterações feitas em um XmlDocument objeto como resultado dos métodos de edição descritos neste tópico é executado usando os XmlDocument métodos da classe. Para obter mais informações sobre como salvar alterações feitas em um XmlDocument objeto, consulte Salvando e gravando um documento.

Consulte também