XML Editing Functions

Atheros provides support for remote PIB management using XML instruction files. The concept is based on an XML schema that defines the elements and attributes needed to edit a PIB file. The schema is located in file piboffset.xsd. In practice, this schema could be used to edit any buffer containing data but we are only interested in editing PIB files here.

Users may create XML files that conform to the schema and specify the PIB objects they want to change and how they want each to change. In brief, the files specify an offset, a data length and a data value. A data value has type dataString, dataHex or dataByte and may be a single data item or an array of data items. Each XML file should include a reference to the Atheros schema and be submitted to a validating XML parser, such as Internet Explorer or Firefox, to ensure that file structure and syntax are correct before use. An example XML file can be seen in piboffset.xml.

Editing involves the following steps. An example of these steps can be seen in the pxe program source code and in function RdModWrPib2.c which is a component of the int6k2 program.

  1. Obtain a copy of the PIB to be edited. This can be done by opening a PIB file and reading the entire file into memory or by requesting the PIB directly from an active Atheros powerline device. The PIB length can be determined from the PIB header.

  2. Open the XML file, generate an XML parse tree and close the file. This can be done by passing the filename to function xmlopen. It will perform all these steps and return the parse tree root node.

  3. Modify the PIB based to instructions stored in the parse tree. This is done by passing the parse tree, PIB buffer and PIB length to function xmledit. It will traverse the parse tree and apply changes to the buffer as defined in the parse tree.

  4. Discard the parse tree. This can be done by passing the parse tree to function xmlfree.

  5. Compute a new PIB checksum. This can be done by clearing the PIB checksum then passing the PIB buffer and PIB length to function checksum32 with a checksum value of 0.

  6. Write the PIB to file or transmit it over the network to an Atheros powerline device.

xmledit

signed xmledit(node,  
 memory,  
 extent); 
struct node * node;
void *memory;
unsigned extent;
 

Write data into memory based on the data offset and length defined in XML parse tree, node. This function will not apply modifications having malformed structure or having an invalid or illegal offset, length or data value. Use function xmlschema to print the current schema. The function is declared in node.h and defined in xmledit.c. The node structure is defined in node.h.

xmlfree

void xmlfree(node); 
struct node * node;
 

Release memory associated with an XML parse tree. The function is declared in node.h and defined in xmlfree.c. The node structure is defined in node.h.

The text member if the parse tree root node points to memory allocated by xmlscan to store the original XML string. The application must either deallocate that memory before calling this function or store the text address and deallocate that memory after calling this function; otherwise, memory leaks will result.

xmlnode

struct node *xmlnode(node); 
struct node *node;
 

Create an empty node blow the specified node and return a pointer to it. A typical application can be seen in function xmlscan.c. The function is declared in node.h and defined in xmlnode.c. The node structure is defined in node.h.

xmlopen

struct node * xmlopen(filename); 
char const * filename;
 

Open the named XML file, parse it and return the XML parse tree. The parse tree contains, among other things, all XML elements, attributes and values specified in the file. The function is declared in node.h and defined in xmlopen.c. The node structure is defined in node.h.

The returned parse tree is ready to traverse using struct node members above, below, prior and after. Each node has a line, type and test member. This function calls function xmlscan to parse the file and generate the tree. The parse tree can be inspected by passing the root node to function xmltree.

xmlscan

signed xmlscan (node); 
struct node * node;
 

Scan the XML string attached to the specified node and create a parse tree below it. Return 0 if parsing is successrul or -1 if not. The function is declared in node.h and defined in xmlscan.c. The node structure is defined in node.h.

The application must point the text member to a copy of the XML string before calling this function because parsing is destructive and requires write access to the string. The application can search and manipulate the tree on return. The application should deallocate string memory before calling xmlfree.

Example 7.4.  XML Source File

The following is sample input to function xmlscan. The element and attribute names shown are for illustration and were selected to that they can be easily identified in the output. The parse tree from this file can be seen in the example for function xmltree.

<?xml version="1.0" encoding="UTF-8" ?>
<xmlfile 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:noNamespaceSchemaLocation="myschema.xsd">
	<element name="Element1">
		<attribute name="Attribute1">
			1234567890
			</attribute>
		<attribute name="Attribute2">
			The quick brown fox jumped over the lazy dog.
			</attribute>
		</element>
	<element name="Element2">
		<attribute name="Attribute1">
			</attribute>
		<attribute name="Attribute2">
			The quick brown 
			fox jumped over 
			the lazy dog.
			</attribute>
		</element>
<!-- comments can go anywhere -->
	<element name="Element2">
		<attribute name="Attribute1"/>
		<attribute name="Attribute2">
			value2
			</attribute>
		</element>
	</xmlfile>

xmlschema

void xmlschema(); 
;
 

Print an XML schema that supports function xmledit on stdout. This function has no argument. The schema produced by this function is guaranteed to support the parse logic implemented by function xmledit. Scheme element names are defined as constants in node.h so that they can be referenced by applications that create their own XML edit instructions. The function is declared in node.h and defined in xmlschema.c.

The text member in the parse tree root node points to memory allocated by xmlscan to store the original XML string. The application must either deallocate that memory before calling this function or store the text address and deallocate that memory after calling this function; otherwise, memory leaks will result.

Example 7.5.  XML Edit Schema

<?xml version='1.0' encoding='UTF-8'?>
<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' elementFormDefault='qualified'>
	<xs:element name='pib'>
		<xs:complexType>
			<xs:sequence>
				<xs:element maxOccurs='unbounded' ref='object'/>
				</xs:sequence>
			</xs:complexType>
		</xs:element>
	<xs:element name='object'>
		<xs:complexType>
			<xs:attribute name='name' use='required' type='xs:NCName'/>
			<xs:sequence>
				<xs:sequence>
					<xs:element ref='offset'/>
					<xs:element ref='length'/>
					</xs:sequence>
				<xs:choice>
					<xs:element ref='array'/>
					<xs:element ref='dataString'/>
					<xs:element ref='dataByte'/>
					</xs:choice>
				</xs:sequence>
			</xs:complexType>
		</xs:element>
	<xs:element name='length' type='xs:positiveInteger'/>
	<xs:element name='offset' type='xs:hexBinary'/>
	<xs:element name='array'>
		<xs:complexType>
			<xs:choice maxOccurs='unbounded'>
				<xs:element ref='dataByte'/>
				<xs:element ref='dataHex'/>
				</xs:choice>
			</xs:complexType>
		</xs:element>
	<xs:element name='dataString' type='xs:string'/>
	<xs:element name='dataHex' type='xs:hexBinary'/>
	<xs:element name='dataByte' type='xs:unsignedByte'/>
	</xs:schema>

The schema shown above was produced by function xmlschema. It is should be used to validate XML edit instructions before submitting them to program pxe.


xmltree

void xmltree(node); 
struct node * node;
 

Print the XML parse tree on stdout. The function is declared in node.h and defined in xmltree.c.

Example 7.6.  XML Parse Tree

The following is sample output from function xmltree. The XML source is shown in the example for function xmlscan . The numbers appearing down the left margin indicate the input line number from the XML source file parsed by function xmlscan . The character codes indicate the node type and are defined in node.h. The node structure is defined in node.h.

001 [?] [xml]
001 [ ] 	[version]
001 [=] 		[1.0]
001 [ ] 	[encoding]
001 [=] 		[UTF-8]
002 [<] [xmlfile]
002 [ ] 	[xmlns:xsi]
002 [=] 		[http://www.w3.org/2001/XMLSchema-instance]
002 [ ] 	[xsi:noNamespaceSchemaLocation]
002 [=] 		[myschema.xsd]
003 [<] 	[element]
003 [ ] 		[name]
003 [=] 			[Element1]
004 [<] 		[attribute]
004 [ ] 			[name]
004 [=] 				[Attribute1]
005 [>] 			[1234567890]
006 [/] 			[attribute]
007 [<] 		[attribute]
007 [ ] 			[name]
007 [=] 				[Attribute2]
008 [>] 			[The quick brown fox jumped over the lazy dog.]
009 [/] 			[attribute]
010 [/] 		[element]
011 [<] 	[element]
011 [ ] 		[name]
011 [=] 			[Element2]
012 [<] 		[attribute]
012 [ ] 			[name]
012 [=] 				[Attribute1]
013 [/] 			[attribute]
014 [<] 		[attribute]
014 [ ] 			[name]
014 [=] 				[Attribute2]
015 [>] 			[The quick brown fox jumped over the lazy dog.azy]
018 [/] 			[attribute]
019 [/] 		[element]
020 [!] 	[-- comments can go anywhere --]
021 [<] 	[element]
021 [ ] 		[name]
021 [=] 			[Element2]
022 [<] 		[attribute]
022 [ ] 			[name]
022 [=] 				[Attribute1]
023 [<] 		[attribute]
023 [ ] 			[name]
023 [=] 				[Attribute2]
024 [>] 			[value2]
025 [/] 			[attribute]
026 [/] 		[element]
027 [/] 	[xmlfile]