delphi yaml
<p>delphi yaml</p><p>https://github.com/lim417dev/Neslib.Yaml</p>
<p>https://github.com/neslib/Neslib</p>
<h1>Neslib.Yaml - A YAML library for Delphi</h1>
<p>Neslib.Yaml is a library for parsing and emitting YAML and constructing YAML documents and streams.</p>
<p>Neslib.Yaml is build on top of the LibYaml library and works on:</p>
<ul>
<li>Windows (32-bit and 64-bit)</li>
<li>MacOS (32-bit and soon 64-bit)</li>
<li>iOS (32-bit and 64-bit, <em>no</em> simulator)</li>
<li>Android (32-bit and 64-bit later)</li>
</ul>
<h2>Installation and Dependencies</h2>
<p>To install:</p>
<div class="highlight highlight-source-shell">
<pre><span class="pl-k">> git clone --recursive https://github.com/neslib/Neslib.Yaml</span></pre>
</div>
<p>This library only depends on the Neslib repository, which is included as submodule with this repository.</p>
<p>For all platforms except MacOS 32-bit, there are no run-time dependencies: the LibYaml library is linked directly into the executable. For MacOS 32-bit, you need to deploy the <code>libyaml_mac32.dylib</code> library to the remote path <code>Contents\MacOS\</code>.</p>
<h2>YAML in a Nutshell</h2>
<p>Here is a very brief introduction for YAML. For more detailed information take a look at the official YAML site or one of the many on-line resources such as this one.</p>
<p>YAML (short for "YAML Ain't Markup Language") is a data serialization language. Unlike many other similar text-based languages (like JSON and XML) a primary goal of YAML is to be human-readable and also easy to create by humans. That's why its is commonly used for configuration files. However, it can be used for all kinds of data, such as this example from the YAML specification:</p>
<div class="highlight highlight-source-yaml">
<pre><span class="pl-ent">invoice: <span class="pl-c1">34843
<span class="pl-ent">date : <span class="pl-c1">2001-01-23
<span class="pl-ent">bill-to: <span class="pl-s">&id001
<span class="pl-ent">given: <span class="pl-s">Chris
<span class="pl-ent">family : <span class="pl-s">Dumars
<span class="pl-ent">address:
<span class="pl-ent">lines: <span class="pl-s">|
<span class="pl-s"> 458 Walkman Dr.
<span class="pl-s"> Suite #292
<span class="pl-s"> <span class="pl-ent">city : <span class="pl-s">Royal Oak
<span class="pl-ent">state : <span class="pl-s">MI
<span class="pl-ent">postal: <span class="pl-c1">48046
<span class="pl-ent">ship-to: <span class="pl-s">*id001
<span class="pl-ent">product:
- <span class="pl-ent">sku : <span class="pl-s">BL394D
<span class="pl-ent">quantity : <span class="pl-c1">4
<span class="pl-ent">description : <span class="pl-s">Basketball
<span class="pl-ent">price : <span class="pl-c1">450.00
- <span class="pl-ent">sku : <span class="pl-s">BL4438H
<span class="pl-ent">quantity : <span class="pl-c1">1
<span class="pl-ent">description : <span class="pl-s">Super Hoop
<span class="pl-ent">price : <span class="pl-c1">2392.00
<span class="pl-ent">tax: <span class="pl-c1">251.42
<span class="pl-ent">total: <span class="pl-c1">4443.52
<span class="pl-ent">comments: <span class="pl-s">>
<span class="pl-s"> Late afternoon is best.
<span class="pl-s"> Backup contact is Nancy
<span class="pl-s"> Billsmer @ 338-4338.</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<p>A YAML document is a tree of values, called nodes (<code>TYamlNode</code> in this library). There are 4 kinds of nodes:</p>
<h3>Mappings</h3>
<p>Mappings are similar to Delphi dictionaries. A mapping is a collection of key/value pairs. The root note of the sample document above is a mapping: it maps the key <code>invoice</code> to the value <code>34843</code> and contains 7 other key/value pairs (from <code>date</code> to <code>comments</code>). Both keys and values can be any YAML type, although you probably want to stick to strings for keys.</p>
<p>Mappings can be written in block notation (as in the example) or flow notation (using curly braces <code>{}</code>).</p>
<p>When using block notation, YAML uses indentation for scoping. Only spaces are allowed for indentation (<em>not</em> tabs). The number of spaces doesn't matter as long as all values at the same level use the same amount of spaces. In the example, the value of the <code>bill-to</code> key is another mapping. This mapping is indented to indicate that it belongs to the <code>bill-to</code>key.</p>
<h3>Sequences</h3>
<p>Sequences are like Delphi arrays or lists. Small sequences can be written using flow notation (using square brackets <code>[]</code>). Larger or complex sequences are usually written in block notation as in the example: the value of the <code>product</code> key is a sequence of two products (a basketball and super hoop). Each item in the sequence starts with a dash and a space.</p>
<p>In this example, each product in the sequence is a mapping of 4 key/value pairs.</p>
<h3>Aliases</h3>
<p>All nodes have at least two properties: a <code>Tag</code> and an <code>Anchor</code>. Tags are used to describe the semantic type of a node. Tags are not that common, so I will skip them in this introduction. Neslib.Yaml has full support for tags though.</p>
<p>An anchor can be used to mark a node in the document. You can then later refer back to this node using an alias.</p>
<p>Anchors are prefixed with an ampersand (<code>&</code>). In the example, the value of the <code>bill-to</code> key has an anchor called <code>id001</code> (the ampersand is not part of the name). Later in the document, the <code>ship-to</code> key refers back to this anchor using an alias (an asterisk followed by the anchor name, eg. <code>*id001</code>). This is a way of saying that the shipping address is the same as the billing address. Note that an alias does not copy the referenced value; it really just refers to another node.</p>
<p>Anchors <em>must</em> appear in the document before they can be referenced. Their names <em>don't</em> have to be unique within the document; if an new anchor is declared with the same name, it replaces the old anchor.</p>
<h3>Scalars</h3>
<p>Scalars are the simplest types. Everything that is not a mapping, sequence or alias is a scalar. In practice, scalars are just strings. All the keys in the example above are string scalars, but a lot of the values are as well (such as <code>34843</code>, <code>2001-01-23</code> and <code>Chris</code>).</p>
<p>The YAML 1.1 specification (which is what LibYaml uses) treats all these scalars as strings, even if they are numbers or dates as in this example. You can use tags to explicitly state that a specific scalar is of a specific type.</p>
<p>The <code>TYamlNode</code> record in this library provides methods like <code>ToInteger</code> and <code>ToDouble</code> to (try to) convert to Delphi types, regardless of any tags that may be attached to a node.</p>
<p>Scalars can be written in different "styles":</p>
<ul>
<li>The plain style is the most common style. It doesn't use any special symbols. Most scalars in the example are in plain style.</li>
<li>The double-quoted style is useful if you need escape sequences in the text.</li>
<li>The single-quoted style can be used if backslashes in text should <em>not</em> be un-escaped (eg. when using Windows file paths).</li>
<li>The literal style can be used for a block of text spanning multiple lines. It starts with a pipe symbol (<code>|</code>). In the example above, the <code>bill-to.address.lines</code> value is a literal. Any new-lines in a literal are preserved.</li>
<li>Finally, the folded style is similar to the literal style, but line breaks are folded (replaced with spaces). It is used with the <code>comments</code> key in the example.</li>
</ul>
<p>There is much more to YAML, but this should cover many use cases.</p>
<h2>Loading or Parsing YAML</h2>
<p>The main entry point to this library is the <code>IYamlDocument</code> or <code>IYamlStream</code> interface.</p>
<p>A YAML file can contain multiple documents. If that is the case, you should use an <code>IYamlStream</code> to load it. A stream is just a collection of documents (of type <code>IYamlDocument</code>).</p>
<p>Most of the time though, a YAML file contains just a single document and it is easier to start with a <code>IYamlDocument</code>. Loading a document is easy:</p>
<div class="highlight highlight-source-pascal">
<pre><span class="pl-k">var
Doc: IYamlDocument;
<span class="pl-k">begin
Doc := TYamlDocument.Load(<span class="pl-s"><span class="pl-pds">'invoice.yaml<span class="pl-pds">');
<span class="pl-k">end;</span></span></span></span></span></span></pre>
</div>
<p>You can load from a file or stream, or you can parse YAML text using the <code>TYamlDocument.Parse</code> method.</p>
<p>You can now use the <code>IYamlDocument.Root</code> property to inspect the document. This property is of type <code>TYamlNode</code>, which is the building block for all documents.</p>
<blockquote>
<p>TYamlNode is implemented as a record to keep it light-weight. All nodes are "owner" by a document. This makes memory management fully automatic: once a document goes out of scope, all its nodes will be freed automatically. This does mean though that you should not "hang on" to nodes after a document has gone out of scope. Doing so results in undefined behavior or access violations.</p>
</blockquote>
<p>For example, to access the <code>price</code> of the first product in the example above, you can use the following code:</p>
<div class="highlight highlight-source-pascal">
<pre>Price := Doc.Root.Values[<span class="pl-s"><span class="pl-pds">'product<span class="pl-pds">'].Nodes[<span class="pl-c1">0].Values[<span class="pl-s"><span class="pl-pds">'price<span class="pl-pds">'].ToDouble;</span></span></span></span></span></span></span></pre>
</div>
<p>You use the <code>Values</code> property to access values by key in <em>mapping</em>. Likewise the <code>Nodes</code> property is used to access values by index in a <em>sequence</em>, and one of the <code>ToXXX</code> methods can be used to convert a <em>scalar</em> value to a Delphi datatype.</p>
<p>To check the type of a node, you can use the <code>NodeType</code> property or one of the <code>IsXXX</code> properties (<code>IsMapping</code>, <code>IsScalar</code> etc.).</p>
<h2>Constructing and Emitting YAML</h2>
<p>You can also create a YAML document from scratch and save it to a file or convert it to YAML. To create a YAML document, use one of the <code>TYamlDocument.CreateXXX</code> methods, depending on the type of root node you need. If you want to reconstruct the example document, you would start out with a mapping and call:</p>
<div class="highlight highlight-source-pascal">
<pre>Doc := TYamlDocument.CreateMapping;</pre>
</div>
<p>You can then start to add key/value pairs"</p>
<div class="highlight highlight-source-pascal">
<pre>Doc.Root.AddOrSetValue(<span class="pl-s"><span class="pl-pds">'invoice<span class="pl-pds">', <span class="pl-c1">34843);
Doc.Root.AddOrSetValue(<span class="pl-s"><span class="pl-pds">'date<span class="pl-pds">', <span class="pl-s"><span class="pl-pds">'2001-01-23<span class="pl-pds">');</span></span></span></span></span></span></span></span></span></span></pre>
</div>
<p>The <code>AddOrSetValue</code> method is used to add key/value pairs to a mapping. If the node is <em>not</em> a mapping, then an <code>EInvalidOperation</code> exception will be raised.</p>
<p>To add a non-scalar value, use one of the other <code>AddOrSetXXX</code> methods:</p>
<div class="highlight highlight-source-pascal">
<pre><span class="pl-k">var
Products: TYamlNode;
<span class="pl-k">begin
Products := Doc.Root.AddOrSetSequence(<span class="pl-s"><span class="pl-pds">'product<span class="pl-pds">');
<span class="pl-k">end;</span></span></span></span></span></span></pre>
</div>
<p>This adds a sequence to the mapping with the key <code>product</code>. You can then add values to the sequence using one of the <code>AddXXX</code> methods. Again, an <code>EInvalidOperation</code> exception will be raised if the node is not a sequence. In the example, we need to add another mapping to this sequence:</p>
<div class="highlight highlight-source-pascal">
<pre><span class="pl-k">var
Product: TYamlNode;
<span class="pl-k">begin
Product := Products.AddMapping;
Product.AddOrSetValue(<span class="pl-s"><span class="pl-pds">'sku<span class="pl-pds">', <span class="pl-s"><span class="pl-pds">'BL394D<span class="pl-pds">');
Product.AddOrSetValue(<span class="pl-s"><span class="pl-pds">'quantity<span class="pl-pds">', <span class="pl-c1">4);
<span class="pl-c"><span class="pl-c">// etc...
<span class="pl-k">end;</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<p>Once you have constructed your document, you can save it to a file or stream using the <code>Save</code> method, or convert it to YAML using the <code>ToYaml</code> method:</p>
<div class="highlight highlight-source-pascal">
<pre><span class="pl-k">var
Yaml: String;
<span class="pl-k">begin
Yaml := Doc.ToYaml;
<span class="pl-k">end;</span></span></span></pre>
</div>
<p>You can pass an optional <code>TYamlOutputSettings</code> record to customize the YAML formatting.</p>
<h2>More Information</h2>
<p>There is more to Neslib.Yaml than described above. For more details you can look at the well-document <code>Neslib.Yaml.pas</code> source file. Additional usage samples can be found in the unit tests, especially in the <code>Tests.Neslib.Yaml.Sample.pas</code> file.</p>
<h2>License</h2>
<p>Neslib.Yaml is licensed under the Simplified BSD License.</p>
<p>See License.txt for details.</p>
</div>
<div id="MySignature" role="contentinfo">
<p>本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/14223698.html</p><br><br>
来源:https://www.cnblogs.com/hnxxcxg/p/14223698.html
頁:
[1]