From: 011netservice@gmail.com Date: 2022-10-30 Subject: readme-XML.txt 歡迎來信交流, 訂購軟體需求. □ 開啟 XML, XSD 檔案 ○ Visual Studio 2022 建議使用. 可即時驗證語法、錯誤提示、以及自動建議 Code Snippets. ○ Visual Studio Code. ○ 任何文字編輯器都可以編輯, 但是會很吃力! 因為以上的工具程式, 不但會檢查語法正確性, 還會自動連結 XML 與 XSD 檔案, 檢驗是否符合 XSD 定義. 因此就不用再管以前的 xsd.exe C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\xsd.exe https://www.w3schools.com/xml/schema_example.asp ref: xsd tool, https://docs.microsoft.com/zh-tw/dotnet/standard/serialization/xml-schema-definition-tool-xsd-exe □ xsdschema.xsd 透過 Visual Studio 2022 Go To Definition 功能, 可經由連結關係, 自動找到 XML 檔案依據的 .xsd Schema 定義. 例如在 C:\Program Files\Microsoft Visual Studio\2022\Community\Xml\Schemas\xsdschema.xsd, .xsd Schema 定義檔案內容, 可清楚的了解 XML 檔案中, 各種元素的定義細節或選項. --------- 2022-07-09 #### xs:DataType 以下表格依據 C:\Program Files\Microsoft Visual Studio\2022\Community\Xml\Schemas\xsdschema.xsd 整理: Data types --------------------- ---------------------------- Name, Note --------------------- ---------------------------- xs:anyURI, xs:base64Binary, xs:boolean, xs:byte, xs:date, YYYY-MM-DD,其中:YYYY 表示年;MM 表示月;DD 表示日 xs:dateTime, YYYY-MM-DDThh:mm:ss xs:decimal, 可以使用十進位制數字表示的實數 xs:double, xs:duration, PnYnMnDTnHnMnS,其中:P 表示時間間隔(必需的);nY 表示年數;nM 表示月數;依次類推 xs:ENTITIES, xs:ENTITY, xs:float, IEEE 的單精度 32 位浮點數 xs:gDay, xs:gMonth, xs:gMonthDay, xs:gYear, xs:gYearMonth, xs:hexBinary, xs:ID, 只能用於元素的屬性 xs:IDREF, xs:IDREFS, 只能用於元素的屬性 xs:int, 最大值為 2147483647、最小值為 -2147483648 xs:integer, 十進位制整數 --------------------- ---------------------------- xs:language, 合法語言 id 的字串 xs:long, 最大值為 9223372036854775807、最小值為 -9223372036854775808 xs:Name, 合法 XML 名稱的字串,可以包含名稱空間字首 xs:NCName, 合法 XML 名稱的字串,不可以包含名稱空間字首 xs:negativeInteger, xs:NMTOKEN, 只能用於元素的屬性 xs:NMTOKENS, --------------------- ---------------------------- xs:nonNegativeInteger, xs:nonPositiveInteger,最大值為 0 --------------------- ---------------------------- xs:normalizedString, 任意字串(會刪除LF、CR 和製表符號等空白字元). xs:NOTATION, xs:positiveInteger, xs:QName, xs:short, --------------------- ---------------------------- xs:string, 任意字串. xs:time, hh:mm:ss,其中:hh 表示時;mm 表示分;ss 表示秒 --------------------- ---------------------------- xs:token, 任意字串.(會刪除LF、CR 和製表符號等空白字元、開頭和結尾的空格、以及連續的空格) xs:unsignedByte, xs:unsignedInt, xs:unsignedLong, xs:unsignedShort --------- 2022-07-09 #### C# XmlDocument class samples XmlDocument Class ref: https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmldocument?view=netframework-4.8&f1url=%3FappId%3DDev16IDEF1%26l%3DEN-US%26k%3Dk(System.Xml.XmlDocument)%3Bk(TargetFrameworkMoniker-.NETFramework%2CVersion%253Dv4.8)%3Bk(DevLang-csharp)%26rd%3Dtrue Definition Namespace: System.Xml Assembly: System.Xml.dll Represents an XML document. You can use this class to load, validate, edit, add, and position XML in a document. public class XmlDocument : System.Xml.XmlNode Remarks The XmlDocument class is an in-memory representation of an XML document. It implements the W3C XML Document Object Model (DOM) Level 1 Core and the Core DOM Level 2. DOM stands for document object model. To read more about it, see XML Document Object Model (DOM). You can load XML into the DOM by using the XmlDocument class, and then programmatically read, modify, and remove XML in the document. If you want to try open the XmlDocument class and see how it's implemented, see the Reference Source. Tasks □ Load XML into the document object model □ Validate it against a schema □ Navigate the document tree □ Find nodes □ Edit nodes □ Add nodes □ Remove nodes □ Position nodes -------------------- □ Load XML into the document object model Start with an XML document like this one that has a few books in a collection. It contains the basic things that you'd find in any XML document, including a namespace, elements that represent data, and attributes that describe the data. Pride And Prejudice 24.95 The Handmaid's Tale 29.95 Sense and Sensibility 19.95 Next, load this data into the DOM so that you can work with it in memory. The most popular way to do this is refer to a file on your local computer or on a network. This example loads XML from a file. If the file doesn't exist, it just generates some XML and loads that. XmlDocument doc = new XmlDocument(); doc.PreserveWhitespace = true; try { doc.Load("booksData.xml"); } catch (System.IO.FileNotFoundException) { doc.LoadXml(" \n" + " \n" + " \n" + " Pride And Prejudice \n" + " 24.95 \n" + " \n" + " \n" + " The Handmaid's Tale \n" + " 29.95 \n" + " \n" + ""); } -------------------- □ Validate it against a schema Start with an XML schema like this one. This schema defines the data types in the XML and which attributes are required. Create an XmlReader object by using your schema, and then load that object into the DOM. Create an event handler that executes when code attempts to modify your XML file in ways that violate the rules of the schema. These blocks of code show helper methods that do all of this. //************************************************************************************ // // Helper method that generates an XML string. // //************************************************************************************ private string generateXMLString() { string xml = " \n" + " \n" + " \n" + " Pride And Prejudice \n" + " 24.95 \n" + " \n" + " \n" + " The Handmaid's Tale \n" + " 29.95 \n" + " \n" + " \n" + " Sense and Sensibility \n" + " 19.95 \n" + " \n" + ""; return xml; } //************************************************************************************ // // Associate the schema with XML. Then, load the XML and validate it against // the schema. // //************************************************************************************ public XmlDocument LoadDocumentWithSchemaValidation(bool generateXML, bool generateSchema) { XmlReader reader; XmlReaderSettings settings = new XmlReaderSettings(); // Helper method to retrieve schema. XmlSchema schema = getSchema(generateSchema); if (schema == null) { return null; } settings.Schemas.Add(schema); settings.ValidationEventHandler += ValidationCallback; settings.ValidationFlags = settings.ValidationFlags | XmlSchemaValidationFlags.ReportValidationWarnings; settings.ValidationType = ValidationType.Schema; try { reader = XmlReader.Create("booksData.xml", settings); } catch (System.IO.FileNotFoundException) { if (generateXML) { string xml = generateXMLString(); byte[] byteArray = Encoding.UTF8.GetBytes(xml); MemoryStream stream = new MemoryStream(byteArray); reader = XmlReader.Create(stream, settings); } else { return null; } } XmlDocument doc = new XmlDocument(); doc.PreserveWhitespace = true; doc.Load(reader); reader.Close(); return doc; } //************************************************************************************ // // Helper method that generates an XML Schema. // //************************************************************************************ private string generateXMLSchema() { string xmlSchema = " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " "; return xmlSchema; } //************************************************************************************ // // Helper method that gets a schema // //************************************************************************************ private XmlSchema getSchema(bool generateSchema) { XmlSchemaSet xs = new XmlSchemaSet(); XmlSchema schema; try { schema = xs.Add("http://www.contoso.com/books", "booksData.xsd"); } catch (System.IO.FileNotFoundException) { if (generateSchema) { string xmlSchemaString = generateXMLSchema(); byte[] byteArray = Encoding.UTF8.GetBytes(xmlSchemaString); MemoryStream stream = new MemoryStream(byteArray); XmlReader reader = XmlReader.Create(stream); schema = xs.Add("http://www.contoso.com/books", reader); } else { return null; } } return schema; } //************************************************************************************ // // Helper method to validate the XML against the schema. // //************************************************************************************ private void validateXML(bool generateSchema, XmlDocument doc) { if (doc.Schemas.Count == 0) { // Helper method to retrieve schema. XmlSchema schema = getSchema(generateSchema); doc.Schemas.Add(schema); } // Use a callback to validate the XML node against the schema. doc.Validate(ValidationCallback); } //************************************************************************************ // // Event handler that is raised when XML doesn't validate against the schema. // //************************************************************************************ void ValidationCallback(object sender, System.Xml.Schema.ValidationEventArgs e) { if (e.Severity == XmlSeverityType.Warning) { Console.WriteLine ("The following validation warning occurred: " + e.Message); } else if (e.Severity == XmlSeverityType.Error) { Console.WriteLine ("The following critical validation errors occurred: " + e.Message); } } -------------------- □ Navigate the document tree You can use properties to navigate around an XML document. But before you use any of them, let's quickly review a few terms. Your document is composed of nodes. Each node has as single parent node directly above it. The only node that does not have a parent node is the document root, as it is the top-level node. Most nodes can have child nodes, which are nodes directly below them. Nodes that are at the same level are siblings. The following examples show you how to obtain the root node, jump to the first child node of the root node, access any of its child nodes, get back out to the parent node, and then navigate across sibling nodes. Start with the root node This example gets the root node and then uses that node to output the contents of the document to the console. using System; using System.IO; using System.Xml; public class Sample { public static void Main() { //Create the XmlDocument. XmlDocument doc = new XmlDocument(); doc.LoadXml("" + "" + "Pride And Prejudice" + ""); //Display the document element. Console.WriteLine(doc.DocumentElement.OuterXml); } } Get child nodes This example jumps to the first child node of the root node and then iterates through the child nodes of that node if any exist. using System; using System.Xml; public class Sample2 { public static void Main() { XmlDocument doc = new XmlDocument(); doc.LoadXml("" + "Pride And Prejudice" + "19.95" + ""); XmlNode root = doc.FirstChild; //Display the contents of the child nodes. if (root.HasChildNodes) { for (int i = 0; i < root.ChildNodes.Count; i++) { Console.WriteLine(root.ChildNodes[i].InnerText); } } } } Get back to the parent node Use the ParentNode property. Refer to the last child node This example writes the price of a book to the console. The price node is the last child of a book node. using System; using System.Xml; public class Sample3 { public static void Main() { XmlDocument doc = new XmlDocument(); doc.LoadXml("" + "Pride And Prejudice" + "19.95" + ""); XmlNode root = doc.FirstChild; Console.WriteLine("Display the price element..."); Console.WriteLine(root.LastChild.OuterXml); } } Navigate forward across siblings This example moves forward from book to book. Book nodes are siblings to one another. using System; using System.Xml; public class Sample4 { public static void Main() { XmlDocument doc = new XmlDocument(); doc.Load("books.xml"); XmlNode currNode = doc.DocumentElement.FirstChild; Console.WriteLine("First book..."); Console.WriteLine(currNode.OuterXml); XmlNode nextNode = currNode.NextSibling; Console.WriteLine("\r\nSecond book..."); Console.WriteLine(nextNode.OuterXml); } } Navigate backwards across siblings This example moves backwards from book to book. using System; using System.Xml; public class Sample { public static void Main() { XmlDocument doc = new XmlDocument(); doc.Load("books.xml"); XmlNode lastNode = doc.DocumentElement.LastChild; Console.WriteLine("Last book..."); Console.WriteLine(lastNode.OuterXml); XmlNode prevNode = lastNode.PreviousSibling; Console.WriteLine("\r\nPrevious book..."); Console.WriteLine(prevNode.OuterXml); } } -------------------- □ Find nodes The most popular way to find one or more nodes of data is to use an XPath query string, but there are also methods that don't require one. Get a single node This example locates a book by using the ISBN number. public XmlNode GetBook(string uniqueAttribute, XmlDocument doc) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); nsmgr.AddNamespace("bk", "http://www.contoso.com/books"); string xPathString = "//bk:books/bk:book[@ISBN='" + uniqueAttribute + "']"; XmlNode xmlNode = doc.DocumentElement.SelectSingleNode(xPathString, nsmgr); return xmlNode; } The string used in this example is an Xpath query. You can find more examples of them here: XPath examples. You can also use the GetElementById to retrieve nodes. To use this approach, you'll have to define ID's in the document type definition declarations of your XML file. After you get a node, you get the value of attributes or child nodes. This example does that with a book node. public void GetBookInformation(ref string title, ref string ISBN, ref string publicationDate, ref string price, ref string genre, XmlNode book) { XmlElement bookElement = (XmlElement)book; // Get the attributes of a book. XmlAttribute attr = bookElement.GetAttributeNode("ISBN"); ISBN = attr.InnerXml; attr = bookElement.GetAttributeNode("genre"); genre = attr.InnerXml; attr = bookElement.GetAttributeNode("publicationdate"); publicationDate = attr.InnerXml; // Get the values of child elements of a book. title = bookElement["title"].InnerText; price = bookElement["price"].InnerText; } Get a collection of nodes This example selects all books where the author's last name is Austen, and then changes the price of those books. using System; using System.Xml; public class Sample6 { public static void Main() { XmlDocument doc = new XmlDocument(); doc.Load("booksort.xml"); XmlNodeList nodeList; XmlNode root = doc.DocumentElement; nodeList = root.SelectNodes("descendant::book[author/last-name='Austen']"); //Change the price on the books. foreach (XmlNode book in nodeList) { book.LastChild.InnerText = "15.95"; } Console.WriteLine("Display the modified XML document...."); doc.Save(Console.Out); } } You can also get a collection of nodes by using the name of the node. For example, this example gets a collection of all book titles. using System; using System.Xml; public class Sample1 { public static void Main() { //Create the XmlDocument. XmlDocument doc = new XmlDocument(); doc.Load("books.xml"); //Display all the book titles. XmlNodeList elemList = doc.GetElementsByTagName("title"); for (int i = 0; i < elemList.Count; i++) { Console.WriteLine(elemList[i].InnerXml); } } } -------------------- □ Edit nodes This example edits a book node and its attributes. public void editBook(string title, string ISBN, string publicationDate, string genre, string price, XmlNode book, bool validateNode, bool generateSchema) { XmlElement bookElement = (XmlElement)book; // Get the attributes of a book. bookElement.SetAttribute("ISBN", ISBN); bookElement.SetAttribute("genre", genre); bookElement.SetAttribute("publicationdate", publicationDate); // Get the values of child elements of a book. bookElement["title"].InnerText = title; bookElement["price"].InnerText = price; if (validateNode) { validateXML(generateSchema, bookElement.OwnerDocument); } } -------------------- □ Add nodes To add a node, use the CreateElement method or the CreateNode method. To add a data node such as a book, use the CreateElement method. For any other type of node such as a comment, whitespace node, or CDATA node, use the CreateNode method. This example creates a book node, adds attributes to that node, and then adds that node to the document. public XmlElement AddNewBook(string genre, string ISBN, string misc, string title, string price, XmlDocument doc) { // Create a new book element. XmlElement bookElement = doc.CreateElement("book", "http://www.contoso.com/books"); // Create attributes for book and append them to the book element. XmlAttribute attribute = doc.CreateAttribute("genre"); attribute.Value = genre; bookElement.Attributes.Append(attribute); attribute = doc.CreateAttribute("ISBN"); attribute.Value = ISBN; bookElement.Attributes.Append(attribute); attribute = doc.CreateAttribute("publicationdate"); attribute.Value = misc; bookElement.Attributes.Append(attribute); // Create and append a child element for the title of the book. XmlElement titleElement = doc.CreateElement("title"); titleElement.InnerText = title; bookElement.AppendChild(titleElement); // Introduce a newline character so that XML is nicely formatted. bookElement.InnerXml = bookElement.InnerXml.Replace(titleElement.OuterXml, "\n " + titleElement.OuterXml + " \n "); // Create and append a child element for the price of the book. XmlElement priceElement = doc.CreateElement("price"); priceElement.InnerText= price; bookElement.AppendChild(priceElement); // Introduce a newline character so that XML is nicely formatted. bookElement.InnerXml = bookElement.InnerXml.Replace(priceElement.OuterXml, priceElement.OuterXml + " \n "); return bookElement; } □ Remove nodes To remove a node, use the RemoveChild method. This example removes a book from the document and any whitespace that appears just before the book node. public void deleteBook(XmlNode book) { XmlNode prevNode = book.PreviousSibling; book.OwnerDocument.DocumentElement.RemoveChild(book); if (prevNode.NodeType == XmlNodeType.Whitespace || prevNode.NodeType == XmlNodeType.SignificantWhitespace) { prevNode.OwnerDocument.DocumentElement.RemoveChild(prevNode); } } -------------------- □ Position nodes You can choose where you want a node to appear in your document by using the InsertBefore and InsertAfter methods. This example shows two helper methods. One of them moves a node higher in a list. The other one moves a node lower. These methods could be used in an application that enables users to move books up and down in a list of books. When a user chooses a book and presses an up or down button, your code could call methods like these to position the corresponding book node before or after other book nodes. //************************************************************************************ // // Summary: Move elements up in the XML. // // //************************************************************************************ public void MoveElementUp(XmlNode book) { XmlNode previousNode = book.PreviousSibling; while (previousNode != null && (previousNode.NodeType != XmlNodeType.Element)) { previousNode = previousNode.PreviousSibling; } if (previousNode != null) { XmlNode newLineNode = book.NextSibling; book.OwnerDocument.DocumentElement.RemoveChild(book); if (newLineNode.NodeType == XmlNodeType.Whitespace | newLineNode.NodeType == XmlNodeType.SignificantWhitespace) { newLineNode.OwnerDocument.DocumentElement.RemoveChild(newLineNode); } InsertBookElement((XmlElement)book, Constants.positionAbove, previousNode, false, false); } } //************************************************************************************ // // Summary: Move elements down in the XML. // // //************************************************************************************ public void MoveElementDown(XmlNode book) { // Walk backwards until we find an element - ignore text nodes XmlNode NextNode = book.NextSibling; while (NextNode != null && (NextNode.NodeType != XmlNodeType.Element)) { NextNode = NextNode.NextSibling; } if (NextNode != null) { XmlNode newLineNode = book.PreviousSibling; book.OwnerDocument.DocumentElement.RemoveChild(book); if (newLineNode.NodeType == XmlNodeType.Whitespace | newLineNode.NodeType == XmlNodeType.SignificantWhitespace) { newLineNode.OwnerDocument.DocumentElement.RemoveChild(newLineNode); } InsertBookElement((XmlElement)book, Constants.positionBelow, NextNode, false, false); } } --------- 2022-07-02 #### Tree Structure Terminology □ Tree Structure Terminology ref: https://en.wikipedia.org/wiki/Tree_(data_structure) ○ A node is a structure which may contain data and connections to other nodes, sometimes called edges or links. Each node in a tree has zero or more child nodes, which are below it in the tree (by convention, trees are drawn with descendants going downwards). A node that has a child is called the child's parent node (or superior). All nodes have exactly one parent, except the topmost root node, which has none. A node might have many ancestor nodes, such as the parent's parent. Child nodes with the same parent are sibling nodes. Typically siblings have an order, with the first one conventionally drawn on the left. Some definitions allow a tree to have no nodes at all, in which case it is called empty. ○ An internal node (also known as an inner node, inode for short, or branch node) is any node of a tree that has child nodes. Similarly, an external node (also known as an outer node, leaf node, or terminal node) is any node that does not have child nodes. ○ The height of a node is the length of the longest downward path to a leaf from that node. The height of the root is the height of the tree. The depth of a node is the length of the path to its root (i.e., its root path). When using zero-based counting, the root node has depth zero, leaf nodes have height zero, and a tree with only a single node (hence both a root and leaf) has depth and height zero. Conventionally, an empty tree (tree with no nodes, if such are allowed) has height −1. ○ Each non-root node can be treated as the root node of its own subtree, which includes that node and all its descendants.[a][1] Other terms used with trees: ○ Neighbor Parent or child. ○ Ancestor A node reachable by repeated proceeding from child to parent. ○ Descendant A node reachable by repeated proceeding from parent to child. Also known as subchild. ○ Degree For a given node, its number of children. A leaf has necessarily degree zero. ○ Degree of tree The degree of a tree is the maximum degree of a node in the tree. ○ Distance The number of edges along the shortest path between two nodes. ○ Level The level of a node is the number of edges along the unique path between it and the root node.[2] This is the same as depth when using zero-based counting. ○ Width The number of nodes in a level. ○ Breadth The number of leaves. ○ Forest A set of one or more disjoint trees. ○ Ordered tree A rooted tree in which an ordering is specified for the children of each vertex. The book The Art of Computer Programming uses the term oriented tree.[3] ○ Size of a tree Number of nodes in the tree. --------- 2022-06-30 #### XPath □ Supported XPath syntax: Syntax Meaning ------------------- ----------------------------------------------------- tag 選擇所有符合 tag 的 child elements。 Ex. spam 選擇所有 name 為 spam 的 child elements; spam/egg 選擇所有在 name 為 spam 的 child elements 中的 name 為 egg 的 grandchildren elements。 ------------------- ----------------------------------------------------- * 選擇所有 child elements。 ------------------- ----------------------------------------------------- . 選擇當前節點 ------------------- ----------------------------------------------------- // 選擇所有 subelements。 Ex. .//egg 選擇 tree 中所有 name 為 egg 的 elements。 ------------------- ----------------------------------------------------- … 選擇 parent element。 ------------------- ----------------------------------------------------- [@attrib] 選擇有 given attribute 的 element。 ------------------- ----------------------------------------------------- [@attrib=‘value’] 選擇所有 given attribute 等於 value 的 elements。(value 不能有引號) ------------------- ----------------------------------------------------- [tag] 選擇 child element 有 given tag 的 element。(限第1層的 child element) ------------------- ----------------------------------------------------- [tag=‘text’] 選擇 child element 的 tag 等於 given text 的 element。(所有後代 element) ------------------- ----------------------------------------------------- [position] index 的作用,可以使用 last()。(1 為起始位置) ------------------- ----------------------------------------------------- 所有的 Predicates (使用中括號) 前面必須要有 tag name、* 或 其他Predicates □ XPath 單引號雙引號使用方式 ref https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmlnode.selectsinglenode?view=netframework-4.8&f1url=%3FappId%3DDev16IDEF1%26l%3DEN-US%26k%3Dk(System.Xml.XmlNode.SelectSingleNode)%3Bk(TargetFrameworkMoniker-.NETFramework%2CVersion%253Dv4.8)%3Bk(DevLang-csharp)%26rd%3Dtrue A common issue when formulating XPath expressions is how to include a single quote (') or double quote (") in the expression. If you have to search for a value that includes a single quote, you must enclose the string in double quotes. If you need to search for a value that includes a double quote, you must enclose the string in single quotes. 單引號(')要放在雙引號(")內, 雙引號(")要放在單引號(')內, 如下例: For example, suppose you have the following XML: 'Emma' The following Visual Basic code selects an element that contains single quotes: Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable) nsmgr.AddNamespace("ab", "http://www.lucernepublishing.com") book = root.SelectSingleNode("descendant::ab:book[ab:title=""'Emma'""]", nsmgr) This method is a Microsoft extension to the Document Object Model (DOM). □ 範例1: document.SelectNodes() 讀取 Element.Attributes: MimeTypes.config 檔案內容: 讀取以上 XML 所有的 mimeMap.mimeType 如下: Dictionary D1 = new Dictionary(); try { XmlDocument document = new XmlDocument(); document.Load(configFileName); foreach (XmlNode node in document.SelectNodes("configuration/system.webServer/staticContent/mimeMap")) { string fileExtension = node.Attributes["fileExtension"].Value; string mimeType = node.Attributes["mimeType"].Value; (D1.Add(fileExtension, mimeType); } } catch (Exception ex) { throw new ConfigurationErrorsException("Invalid Mime Types configuration file: " + configFileName, ex); } □ 範例2: XPath ref: https://dotblogs.com.tw/RhinoGoat/2018/04/17/231849 Empire Burlesque Bob Dylan 10.90 Hide your heart Bonnie Tyler 9.90 Greatest Hits Dolly Parton 9.90 XPath is an emerging standard for directly accessing one or more nodes in an XML document using a simple filename-like syntax. For example, the XPath "/*/author" would select all of the grandchildren named "author", starting the search at the top-level document. Electric XML includes a useful subset of XPath functionality, and supports the following special tokens: name matches all nodes on the current level with the specified name [n] matches the nth node on the current level, with n=1 denoting the first node name[n] matches the nth element on the current level with the specified name * matches all nodes on the current level / if used as the first character, denotes the top-level document, otherwise denotes moving down a level .. go up one level . the current level // the current level and all sublevels to any depth [@key='value'] all elements with an attribute that matches the specified key/value pair name[@key='value'] all elements with the specified name and an attribute that matches the specified key/value pair [text()='value'] all elements with the specified text name[text()='value'] all elements with the specified name and text @name the attribute with the specified name @* all attributes 定位節點 XML是樹狀結構,類似檔案系統內資料夾的結構,XPath也類似檔案系統的路徑命名方式。不過XPath 是一種模式(Pattern),可以選出 XML檔案中,路徑符合某個模式的所有節點出來。 例如要選catalog底下的cd中所有price元素可以用: /catalog/cd/price 如果XPath的開頭是一個斜線(/)代表這是絕對路徑。如果開頭是兩個斜線(//)表示檔中所有符合模式的元素都會被選出來,即使是處於樹中不同的層級也會被選出來。 以下的語法會選出檔中所有叫做cd的元素(在樹中的任何層級都會被選出來): //cd 選擇未知的元素 使用星號(Wildcards,*)可以選擇未知的元素。 下面這個語法會選出/catalog/cd 的所有子元素: /catalog/cd/* 以下的語法會選出所有catalog的子元素中,包含有price作為子元素的元素。 /catalog/*/price 以下的語法會選出有兩層父節點,叫做price的所有元素。 /*/*/price 以下的語法會選擇出檔中的所有元素。 //* 要注意的是,想要存取不分層級的元素,XPath語法必須以兩個斜線開頭(//),想要存取未知元素才用星號(*),星號只能代表未知名稱的元素,不能代表未知層級的元素。 選擇分支 使用中括弧可以選擇分支。以下的語法從catalog的子元素中取出第一個叫做cd的元素。XPath的定義中沒有第0元素這種東西。 /catalog/cd[1] 以下語法選擇catalog中的最後一個cd元素:(XPathj並沒有定義 first() 這種函式喔,用上例的 [1]就可以取出第一個元素。 /catalog/cd[last()] 以下語法選出含有price子元素的所有/catalog/cd元素。 /catalog/cd[price] 以下語法選出price元素的值等於10.90的所有/catalog/cd元素 /catalog/cd[price=10.90] 以下語法選出price元素的值等於10.90的所有/catalog/cd元素 的price元素 /catalog/cd[price=10.90]/price 選擇一個以上的路徑 使用Or運算元(|)就可以選擇一個以上的路徑。例如: /catalog/cd/title | catalog/cd/artist 選擇所有title以及artist元素 //title | //artist 選擇所有title以及artist以及price元素 //title | //artist | //price 選擇屬性 在XPath中,除了選擇元素以外,也可以選擇屬性。屬性都是以@開頭。例如選擇檔中所有叫做country的屬性: //@country 選擇所有含有country這個屬性的cd元素: //cd[@country] 以下語法選擇出含有屬性的所有cd元素 //cd[@*] 以下語法選擇出country屬性值為UK的cd元素 //cd[@country='UK'] 其他 所有,且其Attribute是qty>3 或price>400 descendant::Item[@qty>3 or @price>400]" --------- 2022-06-26 #### 新增 element 到 XML document ref: https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmlelement.ownerdocument?view=netframework-4.8 The following example inserts a new element into an XML document. using System; using System.IO; using System.Xml; public class Sample { public static void Main() { XmlDocument doc = new XmlDocument(); doc.LoadXml("" + "Pride And Prejudice" + ""); XmlElement root = doc.DocumentElement; // Create a new element. XmlElement elem = doc.CreateElement("price"); elem.InnerText="19.95"; // Display the new element's owner document. Note // that although the element has not been inserted // into the document, it still has an owner document. Console.WriteLine(elem.OwnerDocument.OuterXml); // Add the new element into the document. root.AppendChild(elem); Console.WriteLine("Display the modified XML..."); Console.WriteLine(doc.InnerXml); } } When adding nodes to the current node, use the XmlDocument returned by the OwnerDocument property to create the node. --------- 2022-06-26 #### ParentNode 回傳值 /* ParentNode 回傳值 ref: https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmlnode.parentnode?view=netframework-4.8 return values of ParentNode property: NodeType Return Value of ParentNode -------------------------------------------------------- -------------------------------- Attribute, Document, DocumentFragment, Entity, Notation. Returns null; these nodes do not have parents. 這些沒有 parents, 所以回傳 null. -------------------------------------------------------- -------------------------------- CDATA Returns the element or entity reference containing the CDATA section. -------------------------------------------------------- -------------------------------- Comment Returns the element, entity reference, document type, or document containing the comment. -------------------------------------------------------- -------------------------------- DocumentType Returns the document node. root node 的上層為 document node. -------------------------------------------------------- -------------------------------- Element Returns the parent node of the element. If the element is the root node in the tree, the parent is the document node. 回傳上層的 Element. 若為 root node, 則回傳 document node. -------------------------------------------------------- -------------------------------- EntityReference Returns the element, attribute, or entity reference containing the entity reference. -------------------------------------------------------- -------------------------------- ProcessingInstruction Returns the document, element, document type, or entity reference containing the processing instruction. -------------------------------------------------------- -------------------------------- Text Returns the parent element, attribute, or entity reference containing the text node. -------------------------------------------------------- -------------------------------- NodeType Return Value of ParentNode -------------------------------------------------------- -------------------------------- */ --------- 2022-06-25 #### 以 XSD 檢驗 XML 檔案 □ 範例1 ref: https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmldocument.validate?view=netframework-4.8&f1url=%3FappId%3DDev16IDEF1%26l%3DEN-US%26k%3Dk(System.Xml.XmlDocument.Validate)%3Bk(TargetFrameworkMoniker-.NETFramework%2CVersion%253Dv4.8)%3Bk(DevLang-csharp)%26rd%3Dtrue The following example illustrates use of the Validate method. The example creates an XmlDocument that contains an associated XSD schema using the XmlReaderSettings and XmlReader objects. The example then uses the XPathNavigator class to incorrectly modify the typed value of an element in the XML document generating a schema validation error. using System; using System.Xml; using System.Xml.Schema; using System.Xml.XPath; class XPathValidation { static void Main() { try { 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); ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler); // the following call to Validate succeeds. document.Validate(eventHandler); // add a node so that the document is no longer valid XPathNavigator navigator = document.CreateNavigator(); navigator.MoveToFollowing("price", "http://www.contoso.com/books"); XmlWriter writer = navigator.InsertAfter(); writer.WriteStartElement("anotherNode", "http://www.contoso.com/books"); writer.WriteEndElement(); writer.Close(); // the document will now fail to successfully validate document.Validate(eventHandler); } catch (Exception ex) { Console.WriteLine(ex.Message); } } static void ValidationEventHandler(object sender, ValidationEventArgs e) { switch (e.Severity) { case XmlSeverityType.Error: Console.WriteLine("Error: {0}", e.Message); break; case XmlSeverityType.Warning: Console.WriteLine("Warning {0}", e.Message); break; } } } The example takes the contosoBooks.xml and contosoBooks.xsd files as input. The Autobiography of Benjamin Franklin Benjamin Franklin 8.99 The Confidence Man Herman Melville 11.99 The Gorgias Plato 9.99 Remarks The Validate method validates the XML data in the XmlDocument against the schemas contained in the Schemas property. The Validate method performs infoset augmentation. Specifically, after successful validation, schema defaults are applied, text values are converted to atomic values as necessary, and type information is associated with validated information items. The result is a previously un-typed XML sub-tree in the XmlDocument replaced with a typed sub-tree. The following are important notes to consider when using the Validate method. 1. Schema location hints like xsi:schemaLocation or xsi:noNamespaceSchemaLocation are ignored. 2. Inline schemas are ignored. 3. If schema validation errors occur during validation the XmlDocument becomes partially validated with some nodes with correct type information and some without. 4. The validation process includes checking for uniqueness and reference constraints (xs:ID, xs:IDREF, xs:key, xs:keyref, and xs:unique). --------- 2022-06-25 #### nillable="true" VS xsi:nil https://www.codeproject.com/Questions/829149/xsd-doesnt-work-with-nullable-value An element like does not declare a null element, but an empty element (0 length string). 以上不是建立 null element, 而是建立一個 empty element (長度為0的字串). To make an exiting element that is nullable you have explicitly state it... An other option is to set minOccurs to 0 and remove the element completely when it is null... 建立 nullable element 的正確方法是加入 xsi:nil="true", 或是將 minOccurs 設為 0. todo --------- 2022-06-25 #### XML 序列化的範例 ref: https://docs.microsoft.com/zh-tw/dotnet/standard/serialization/examples-of-xml-serialization --------- 2022-06-19 #### xsd:all, xsd:sequence, xsd:choice, or xsd:group When to use xsd:all, xsd:sequence, xsd:choice, or xsd:group: ref: https://stackoverflow.com/questions/36286056/the-difference-between-all-sequence-choice-and-group-in-xsd Use xsd:all when all child elements must be present, independent of order. Use xsd:sequence when child elements must be present per their occurrence constraints and order does matters. Use xsd:choice when one of the child element must be present. Use xsd:group as a way to wrap any of the above in order to name and reuse in multiple locations within an XSD. Note that occurrence constraints can appear on xsd:all, xsd:sequence, or xsd:choice in addition to the child elements to achieve various cardinality effects. --------- 2022-06-17 #### XML reference an XML Schema(XSD) ref: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms757863(v=vs.85) To reference an XML Schema (XSD) schema from an XML document in MSXML 6.0, you can use any one of the following means to link a schema to an XML document so that MSXML will use the schema to validate the document contents. 1. Reference the XSD schema in the XML document using XML schema instance attributes such as either xsi:schemaLocation or xsi:noNamespaceSchemaLocation. 2. Add the XSD schema file to a schema cache and then connect that cache to the DOM document or SAX reader, prior to loading or parsing the XML document. 在 MSXML 6.0 中, XML 檔案參考到 XSD 檔案有兩種方式: 1. 使用 attribute 例如 xsi:schemaLocation 或 xsi:noNamespaceSchemaLocation. 2. 在讀檔解析之前, 將 XSD 檔案存放在 schema cache 中, 讓 DOM 或是 SAX 可以連接讀取. Using noNamespaceSchemaLocation 使用 noNamespaceSchemaLocation The xsi:noNamespaceSchemaLocation attribute works well in situations where namespaces are not used within the XML document contents you want to validate. For example, the following shows an XML document that references an external XSD schema, MyData.xsd, that is located on a Web server. 當沒有用到 (前置符號 namespace) 時, 可以使用 xsi:noNamespaceSchemaLocation 指定. 例如下例, 指定 MyData.xsd 檔案在網站上: Presenting XML Richard Light If the MyData.xsd file exists and is reachable at the Web location stated in the xsi:noNamespaceSchemaLocation attribute, it will be used to validate the node and any of its children nodes that are not namespace prefixed. If a Web server is not available, you can also locate the XSD file in the same directory as the XML file above or use a file-system URL. 若上例中, 在指定的網站上可以找到 MyData.xsd 檔案, 則會引用為 端點以下的檢驗依據. 若不能存放 XSD檔案在網站上, 則可以放在(跟 XML 檔案相同的目錄中), 或者以檔案路徑的方式指定. If you use a file-based URL, be sure to escape the URL value correctly when you write in the xsi:noNamespaceSchemaLocation attribute. For instance, if you have a schema file on your system at the following path: C:\Documents and Settings\All Users\Application Data\My Application\MyData.xsd You need to reformat the URL string so it is escaped properly so it can be used validly like this to locate the file: xsi:noNamespaceSchemaLocation="file://C://Documents and Settings//All Users//Application Data//My Application//MyData.xsd" 若以檔案路徑的方式指定 XSD 檔案, 則要注意 URL 路徑格式要正確, 例如: C:\Documents and Settings\All Users\Application Data\My Application\MyData.xsd 則應寫成: xsi:noNamespaceSchemaLocation="file://C://Documents and Settings//All Users//Application Data//My Application//MyData.xsd" Another possibility is to place the schema in the same directory as the XML that references it. In this case, you only need to specify the file name such as "Mydata.xsd" for MSXML to locate and use the file. 也可以將 XSD 檔案放在 (跟 XML 檔案相同的目錄中). Note If the Mydata.xsd file is not valid XML, MSXML will ignore it and validate for well-formed XML only. To avoid this type of outcome, its a good practice to always validate your schema files first prior to attempting to use them in validation of other documents. 注意若 XSD 檔案不正確時, 則只會檢驗 XML 檔案是否為良好格式的 XML 檔案. 因此 XSD 檔案前, 最好先確認 XSD 檔案本身格式正確後, 再引用來檢驗 XML 檔案. Using schemaLocation 使用 schemaLocation The xsi:schemaLocation attribute works well in situations where namespace prefixes are explicitly declared and used in the XML document you want to validate. The following example shows an XML document that references an external XSD schema, MyData.xsd for us in validating nodes that are in the 'urn:MyData' namespace URI , which is mapped to the "MyData:" namespace prefix. 當使用(前置符號 namespace)時, 可以 xsi:schemaLocation 指定 XSD 檔案位置, 如下例: (前置符號 namespace) "MyData:" 會以 http://www.example.com/MyData.xsd 作為檢驗依據. Presenting XML Richard Light In order for the MyData.xsd file to be paired with and used you to validate elements and attribute nodes that start with the "MyData:", the schema needs to use and contain the following schema attributes: 再改成如下, 可以省略掉在每一個元素前放置(前置符號 namespace) These attributes declare the 'urn:MyData' namespace URI and the "MyData:" namespace prefix so that they correspond identically to how these declarations were made in the XML file. If they do not match, the schema at the specified location would never be invoked during validation. In this example, we show that the schema is Web-hosted at the 'http://www.example.com' Web site. You could, optionally, locate the XSD file in the same directory as the XML file above or use a file-system URL. 以上範例指定 XSD 檔案在網站上, 你也可以指定 XSD 檔案在(跟 XML 檔案相同的目錄中) If you use a file-based URL, be sure to escape the URL value correctly when you write in the xsi:schemaLocation attribute. For instance, if you have a schema file on your system at the following path: C:\Documents and Settings\All Users\Application Data\My Application\MyData.xsd You need to reformat the URL string so it is escaped properly so it can be used validly like this to locate the file: xsi:schemaLocation="urn:MyData file://C://Documents and Settings//All Users//Application Data//My Application//MyData.xsd" Another possibility is to place the schema in the same directory as the XML that references it. In this case, you only need to specify the file name like this: xsi:schemaLocation="urn:MyData MyData.xsd" for MSXML to locate and use the file. --------- 2022-06-14 #### xsd Vs xsi xsd and xsi Similarities 1. Both are XML namespace prefixes, abbreviations for an XML namespace. 2 .Both are, as are all namespace prefixes, arbitrarily named; other namespace prefix abbreviations could equally well be used. However, both prefixes are conventional and therefore recommended. (An also-conventional alternative to xsd is xs.) xsd and xsi Differences 1. The xsd (or xs) prefix referring to the Schema Namespace (http://www.w3.org/2001/XMLSchema) is used in XML Schemas (XSDs) for the elements, attributes, and types of the W3C XML Schema Recommendation itself. (This is possible because XML Schema is itself XML.) 2. The xsi prefix referring to the The Schema Instance Namespace http://www.w3.org/2001/XMLSchema-instance is used in XML document instances for several special attributes defined by the XML Schema Recommendation: a. xsi:type allows an XML instance to associate element type information directly rather than through an XSD. See How to restrict the value of an XML element using xsi:type in XSD? b. xsi:nil allows an empty element to be considered to be valid when the XSD might not otherwise have allowed it. c. xsi:schemaLocation and xsi:noNamespaceSchemaLocation provide hints to the XML processor as to how to associate an XSD with an XML document. Use xsi:schemaLocation when there is a namespace; use xsi:noNamespaceSchemaLocation when there is no namespace. --------- 2022-06-14 #### w3schools scehma example https://www.w3schools.com/xml/schema_example.asp An XML Document Let's have a look at this XML document called "shiporder.xml": John Smith Ola Nordmann
Langgt 23
4000 Stavanger Norway
Empire Burlesque Special Edition 1 10.90 Hide your heart 1 9.90
The XML document above consists of a root element, "shiporder", that contains a required attribute called "orderid". The "shiporder" element contains three different child elements: "orderperson", "shipto" and "item". The "item" element appears twice, and it contains a "title", an optional "note" element, a "quantity", and a "price" element. The line above: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" tells the XML parser that this document should be validated against a schema. The line: xsi:noNamespaceSchemaLocation="shiporder.xsd" specifies WHERE the schema resides (here it is in the same folder as "shiporder.xml"). xsi:noNamespaceSchemaLocation 指定 shiporder.xsd 檔案存放在 shiporder.xml 同一個目錄中. Create an XML Schema Now we want to create a schema for the XML document above. Here is the complete listing of the schema file called "shiporder.xsd": Divide the Schema The previous design method is very simple, but can be difficult to read and maintain when documents are complex. The next design method is based on defining all elements and attributes first, and then referring to them using the ref attribute. Here is the new design of the schema file ("shiporder.xsd"): Using Named Types The third design method defines classes or types, that enables us to reuse element definitions. This is done by naming the simpleTypes and complexTypes elements, and then point to them through the type attribute of the element. Here is the third design of the schema file ("shiporder.xsd"): The restriction element indicates that the datatype is derived from a W3C XML Schema namespace datatype. So, the following fragment means that the value of the element or attribute must be a string value: The restriction element is more often used to apply restrictions to elements. Look at the following lines from the schema above: This indicates that the value of the element or attribute must be a string, it must be exactly six characters in a row, and those characters must be a number from 0 to 9. ---------- 2022-06-10 #### Recursion in an XML schema? https://stackoverflow.com/questions/148988/recursion-in-an-xml-schema solution 1: solution 2: solution 3: The other solutions work great for making root elements recursive. However, in order to make a non-root element recursive without turning it into a valid root element in the process, a slightly different approach is needed. Let's say you want to define an XML message format for exchanging structured data between nodes in a distributed application. It contains the following elements: - the root element; - the message's origin; - the message's destination; - the data structure type encoded in the message; - the data contained in the message. In order to support complex data types, is a recursive element. This makes possible to write messages as below, for sending e.g. a geometry_msgs/TwistStamped message to a flying drone specifying its linear and angular (i.e. rotating) speeds: recursive1.xml: controller:8080 drone:8080 geometry_msgs/TwistStamped 0 1 0 base_link 1.0 0 1.0 0.3 0 0 We can easily write an XML schema to validate this format: recursive1.xsd: 上面的驗證方式, 當 為 root element 時, 也會通過驗證. The problem with the schema above is that it makes a root element, which means it also validates the document below: 0 1 0 base_link 1.0 0 1.0 0.3 0 0 為了避免以上的問題, 可以先定義一個 data type, 再定義一個 message 的 data element 如下: In order to avoid this side-effect, instead of defining the element directly at the global level, we first define a data type, then define a data element of that type inside message: Notice that we end up having to define the element twice — once inside the data type, and again inside — but apart a little work duplication this is of no consequence.