入门
XML 文档结构
XML 文档以 XML 声明开头。元素必须正确嵌套和闭合。属性提供额外元数据。xmlns 声明 XML 命名空间以避免命名冲突。
<?xml version="1.0" encoding="UTF-8"?>
<!-- This is a comment -->
<bookstore xmlns="https://example.com/books">
<book id="b1" category="fiction">
<title lang="en">The Great Gatsby</title>
<author>F. Scott Fitzgerald</author>
<price currency="USD">12.99</price>
</book>
<book id="b2" category="programming">
<title lang="en">XML Guide</title>
<author>John Doe</author>
<price currency="USD">29.99</price>
</book>
</bookstore>XML 声明
XML 声明是序言的第一行。'version' 必填(1.0 或 1.1)。'encoding' 默认 UTF-8。'standalone' 告诉解析器是否需要外部 DTD 声明。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- version is required; encoding and standalone are optional -->
<!-- encoding defaults to UTF-8 -->
<!-- standalone="yes" means no external markup declarations -->
<root>
<child>text</child>
</root>注释与处理指令
注释用 <!-- -->,不能嵌套,内部不能含 '--'。处理指令(PI)如 xml-stylesheet 向解析器传递应用特定信息。PI 用 <?target data?>。
<?xml version="1.0"?>
<!-- a comment: ignored by the parser, cannot contain -- -->
<?xml-stylesheet type="text/xsl" href="style.xsl"?>
<root>
<!-- comments can span
multiple lines -->
<item>data</item>
</root>良构 XML
良构(well-formed)指:单一根元素、正确嵌套、所有标签闭合、属性加引号、无重复属性。文档必须良构才能被解析;有效性(对照 DTD/Schema)是可选的。
<!-- WELL-FORMED: single root, properly nested, closed -->
<root>
<a>
<b>text</b>
</a>
</root>
<!-- NOT well-formed: two roots, overlapping tags -->
<!-- <a><b></a></b> -->
<!-- <x></x><y></y> (no single root) -->
<!-- All attributes must be quoted -->
<item id='1' type="x"/>XML 序言与空白
序言包含 XML 声明和可选的 DOCTYPE。xml:space='preserve' 告诉解析器保留空白;'default' 允许常规处理。元素之间的空白通常无意义。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root SYSTEM "root.dtd">
<root xml:space="preserve">
<item> spaced text </item>
<item xml:space="default"> trimmed </item>
</root>CDATA 概览
CDATA 段标记解析器不应解释为标记的文本。CDATA 内 <、>、& 无需转义。CDATA 不能嵌套,且不能包含字面量 ']]>'。
<?xml version="1.0"?>
<root>
<code><![CDATA[
if (a < b && c > d) {
console.log("no escaping needed: < > & ");
}
]]></code>
</root>元素与属性
元素与属性的取舍
属性适合元数据(id、type、标志);元素适合有结构或重复值的数据。一个属性在每个元素只出现一次,且不能承载嵌套结构。无严格规则——一致性最重要。
<!-- Attributes: metadata/identifiers; Elements: data -->
<person id="p1">
<name>Alice</name>
<age>30</age>
</person>
<!-- vs. putting everything in attributes -->
<person id="p1" name="Alice" age="30"/>
<!-- Rule of thumb: use elements for data you display,
attributes for IDs, types, and metadata -->空元素
空元素没有内容。自闭合形式 <tag/> 是 <tag></tag> 的简写。'/>' 前的空格是为可读性和 XHTML 兼容性的风格约定。
<!-- Three equivalent empty-element forms -->
<br></br>
<br/>
<br />
<!-- empty element with attributes -->
<img src="logo.png" alt="Logo" width="200" height="100"/>
<!-- self-closing with namespace -->
<xlink:link xmlns:xlink="http://www.w3.org/1999/xlink" href="#sec1"/>嵌套元素
元素按层级嵌套,必须以相反顺序闭合——不能重叠。嵌套表达结构。过深的树虽合法,但会影响可读性和解析性能。
<library>
<section name="fiction">
<book>
<title>Book A</title>
<authors>
<author>Author 1</author>
<author>Author 2</author>
</authors>
</book>
</section>
</library>
<!-- WRONG: tags must not overlap -->
<!-- <a><b></a></b> -->属性值与引号
属性值必须用单引号或双引号括起。双引号内的双引号必须转义为 "。一个属性在每个元素最多出现一次——重复值请用子元素。
<!-- Both single and double quotes are allowed -->
<item id="q1" name='quick'/>
<msg text="He said "hi""/>
<msg text='She said 'hi''/>
<!-- attribute values MUST be quoted -->
<!-- <item id=q1/> is NOT well-formed -->
<!-- an attribute can appear at most once per element -->
<point x="1" y="2" z="3"/>默认与固定属性
DTD 属性声明支持 #REQUIRED(必须出现)、#IMPLIED(可选)、#FIXED(常量值)和字面量默认值。#FIXED 属性必须始终等于其声明值,否则文档无效。
<!-- In a DTD, attributes can have defaults -->
<!ATTLIST item
type CDATA "standard"
status CDATA #REQUIRED
version CDATA #FIXED "1.0"
note CDATA #IMPLIED>
<item status="active"/>
<!-- 'type' defaults to "standard", 'version' is fixed,
'note' is optional (#IMPLIED) -->元素命名规则
元素名必须以字母或下划线开头,可含字母、数字、连字符、下划线和点。名字不能以 'xml'(任何大小写)开头。XML 大小写敏感,<Tag> 与 <tag> 不同。
<!-- Names: start with a letter or underscore,
continue with letters, digits, hyphens, underscores, dots -->
<my-element>ok</my-element>
<my.element>ok</my.element>
<my_element>ok</my_element>
<_private>ok</_private>
<x-1>ok</x-1>
<!-- NOT allowed: starting with a digit or 'xml', containing spaces -->
<!-- <2way/> -->
<!-- <my element/> -->
<!-- <XmlTag/> (names are case-sensitive; 'xml' prefix is reserved) -->命名空间
默认命名空间
默认命名空间(xmlns=URI)作用于声明它的元素及所有无前缀的后代。子元素继承它,除非被覆盖。属性从不使用默认命名空间。
<?xml version="1.0"?>
<table xmlns="http://www.w3.org/1999/xhtml">
<tr>
<td>Cell content</td>
<td>More content</td>
</tr>
</table>
<!-- All elements without a prefix use the default namespace -->命名空间前缀
命名空间前缀用 xmlns:prefix=URI 声明,以 prefix:element 形式使用。前缀只是别名——只有 URI 决定身份。前缀大小写敏感。
<?xml version="1.0"?>
<root xmlns:bk="https://example.com/books"
xmlns:au="https://example.com/authors">
<bk:book bk:id="b1">
<au:author au:name="Jane Doe"/>
<bk:title>XML Guide</bk:title>
</bk:book>
</root>多命名空间
单个文档可混合多个命名空间。每个前缀声明一次(通常在根元素上)并复用。在元素上声明命名空间会作用于该元素及其后代。
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<m:GetPrice xsi:type="xsd:string"
xmlns:m="https://example.com/pricing">
<m:Item>Apples</m:Item>
</m:GetPrice>
</soap:Body>
</soap:Envelope>命名空间作用域
命名空间声明的作用域限于声明它的元素及其后代。子元素内的重新声明会覆盖父元素的前缀映射(仅对该子树)。子元素闭合后,原映射恢复。
<?xml version="1.0"?>
<root xmlns:a="http://a.example">
<a:item>A</a:item>
<child xmlns:a="http://b.example">
<!-- here 'a' is REBOUND to the b.example URI -->
<a:item>B</a:item>
</child>
<!-- outside child, 'a' is back to a.example -->
<a:item>A again</a:item>
</root>常见命名空间
这些 URI 是众所周知的标识符,不是必须获取的 URL。xsi 命名空间提供 schema-instance 属性(type、nil、schemaLocation)。XSD、XSL、SVG、SOAP、Atom 和 Dublin Core(dc)各有标准 URI。
<!-- Frequently used namespace URIs -->
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd = "http://www.w3.org/2001/XMLSchema"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:svg = "http://www.w3.org/2000/svg"
xmlns:html = "http://www.w3.org/1999/xhtml"
xmlns:soap = "http://schemas.xmlsoap.org/soap/envelope/"
xmlns:atom = "http://www.w3.org/2005/Atom"
xmlns:dc = "http://purl.org/dc/elements/1.1/"XSD 中的目标命名空间
schema 的 targetNamespace 是它所定义元素的命名空间。elementFormDefault='qualified' 表示局部声明的元素属于目标命名空间。tns 前缀是 'this namespace' 的约定。
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://example.com/orders"
xmlns:tns="https://example.com/orders"
elementFormDefault="qualified">
<xs:element name="order" type="tns:OrderType"/>
<xs:complexType name="OrderType">
<xs:sequence>
<xs:element name="item" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>CDATA 与实体
预定义实体
XML 预定义五个实体:<(<)、>(>)、&(&)、'(')、"(")。& 必须始终转义(即使在非 CDATA 文本中);< 除作为标签起始外必须转义;引号主要在属性中需注意。
<?xml version="1.0"?>
<root>
<lt>less than: <</lt>
<gt>greater than: ></gt>
<amp>ampersand: &</amp>
<apos>apostrophe: '</apos>
<quot>quote: "</quot>
<!-- < > & ' " are the 5 built-in entities -->
</root>字符引用
字符引用使用 Unicode 码点:©(十进制)或 ©(十六进制)表示 ©。它们在元素文本和属性值中都有效,不受编码影响。可表示任意 Unicode 字符。
<?xml version="1.0" encoding="UTF-8"?>
<root>
<decimal>© 2024 Company</decimal>
<hex>© 2024 Company</hex>
<euro>Price: €10</euro>
<emoji>Smile: 😀</emoji>
</root>
<!-- &#NNN; decimal code point -->
<!-- &#xHHH; hexadecimal code point -->CDATA 段
CDATA 段让你无需转义即可包含 <、>、&——适合代码和标记。CDATA 不能字面包含 ']]>';要嵌入它,按所示拆分段。CDATA 是字符数据,不被解析为元素。
<?xml version="1.0"?>
<root>
<script><![CDATA[
function check(a, b) {
if (a < b && b > 0) {
return a & b;
}
}
]]></script>
<!-- to include ]]> inside CDATA, split it -->
<data><![CDATA[foo]]]]><![CDATA[>bar]]></data>
</root>自定义实体(DTD)
内部实体在 DTD 中声明,在引用处展开。它们像文本宏,可引用其他实体。适合重复样板文本。注意:外部/通用实体可能是 XXE 安全风险。
<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY company "Acme Corp.">
<!ENTITY version "2.0">
<!ENTITY copyright "Copyright © 2024 &company;">
]>
<root>
<product>&company; Toolkit v&version;</product>
<footer>©right;</footer>
</root>
<!-- Entities are expanded during parsing -->属性中的转义
在属性值内必须把 & 转义为 &,并转义用于界定值的引号(" 或 ')。< 也应转义。属性中的换行和制表符会被解析器规范化为空格。
<?xml version="1.0"?>
<root>
<link url="https://example.com?a=1&b=2"/>
<msg text="Say "hello" & smile"/>
<path value='C:\Users\name'/>
<data value="<tagged>"/>
</root>参数实体
参数实体(用 % 声明)仅在 DTD 内使用,用于构建可复用的内容模型。引用形式为 %name;(带分号)。通用实体(&name;)用于文档内容。
<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY % inline " (#PCDATA | em | strong)* ">
<!ELEMENT p %inline;>
<!ELEMENT em %inline;>
<!ELEMENT strong %inline;>
<!ELEMENT root (p)*>
]>
<root>
<p>Hello <em>world</em> and <strong>XML</strong>.</p>
</root>DTD(文档类型定义)
内部 DTD
内部 DTD 在 DOCTYPE 的方括号内内联声明。它定义结构:存在哪些元素、它们的内容模型和属性。内部 DTD 自包含,但只适用于那一个文档。
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to, from, heading, body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>Alice</to>
<from>Bob</from>
<heading>Reminder</heading>
<body>Don't forget the meeting</body>
</note>外部 DTD
外部 DTD 存放在单独的 .dtd 文件中,用 SYSTEM(私有)或 PUBLIC(公共标识符 + URI)引用。外部 DTD 让多个文档共享一份定义。SYSTEM 'file.dtd' 是最常见形式。
<!-- File: note.dtd -->
<!ELEMENT note (to, from, body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT body (#PCDATA)>
<!-- File: note.xml -->
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Alice</to>
<from>Bob</from>
<body>Hello</body>
</note>元素声明
内容模型用 ,(序列)、|(选择)、?(0-1)、*(0+)、+(1+)。#PCDATA 是文本;混合内容允许文本与元素交错。EMPTY 表示无内容;ANY 禁用检查(生产环境避免使用)。
<!ELEMENT root (child1, child2*)>
<!-- content model operators -->
<!ELEMENT list (item+)> <!-- one or more item -->
<!ELEMENT opt (item?)> <!-- zero or one item -->
<!ELEMENT any (item1 | item2)*> <!-- choice, any number -->
<!ELEMENT text (#PCDATA)> <!-- parsed character data -->
<!ELEMENT mixed (#PCDATA | em)*> <!-- mixed content -->
<!ELEMENT empty EMPTY> <!-- no content -->
<!ELEMENT any ANY> <!-- any content -->属性声明
ATTLIST 声明属性的类型和默认值。ID 是唯一标识符;IDREF/IDREFS 引用 ID(用于交叉链接)。NMTOKEN 是名称令牌。枚举类型列出允许值。默认值:#REQUIRED、#IMPLIED、#FIXED 或字面量。
<!ATTLIST book
id ID #REQUIRED
category CDATA #IMPLIED
lang NMTOKEN "en"
status (draft|final) "draft"
version CDATA #FIXED "1.0">
<!-- Types: CDATA, ID, IDREF, IDREFS, NMTOKEN, NMTOKENS,
NOTATION, enumerated (a|b|c) -->
<!ATTLIST link ref IDREF #REQUIRED>实体声明
通用实体(&name;)在内容中展开;参数实体(%name;)在 DTD 中展开。外部已解析实体包含其他 XML;未解析实体(带 NDATA)指向非 XML 数据,通过 NOTATION 引用。外部实体可导致 XXE 注入。
<!DOCTYPE root [
<!-- internal general entity -->
<!ENTITY name "Alice">
<!-- external parsed entity -->
<!ENTITY chap1 SYSTEM "chapter1.xml">
<!-- unparsed entity (binary, e.g. image) -->
<!ENTITY logo SYSTEM "logo.png" NDATA image>
<!-- notation declaration for unparsed entities -->
<!NOTATION image SYSTEM "image/png">
<!-- parameter entity (DTD-only) -->
<!ENTITY % block "(p | list)+">
]>
<root>&name;</root>DTD 验证
验证检查文档是否匹配其 DTD(元素顺序、允许的属性、ID 唯一性)。标准 DOM 解析器如 minidom 默认不验证——使用 lxml(Python)、xmllint(命令行)或验证型解析器。
<?xml version="1.0"?>
<!DOCTYPE root SYSTEM "schema.dtd">
<root>
<item id="x1">valid</item>
</root>
<!-- Validate with Python: -->
<!-- import xml.dom.minidom as m
dom = m.parse("file.xml")
# minidom does NOT validate; use lxml: -->
<!-- from lxml import etree
dtd = etree.DTD("schema.dtd")
tree = etree.parse("file.xml")
print(dtd.validate(tree)) -->XML Schema(XSD)
Schema 结构
XSD 本身是 XML 文档。根 <schema> 声明 XSD 命名空间和它所定义元素的目标命名空间。elementFormDefault='qualified' 把局部元素放入目标命名空间。
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://example.com/order"
xmlns:tns="https://example.com/order"
elementFormDefault="qualified">
<xs:element name="order" type="tns:OrderType"/>
<xs:complexType name="OrderType">
<xs:sequence>
<xs:element name="customer" type="xs:string"/>
<xs:element name="total" type="xs:decimal"/>
</xs:sequence>
<xs:attribute name="id" type="xs:ID" use="required"/>
</xs:complexType>
</xs:schema>简单类型
simpleType 用约束面(pattern、minInclusive、enumeration、length 等)限制基类型。简单类型只有文本内容和属性——无子元素。可在整个 schema 中复用。
<xs:simpleType name="emailType">
<xs:restriction base="xs:string">
<xs:pattern value="[^@]+@[^@]+.[^@]+"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ageType">
<xs:restriction base="xs:integer">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="120"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="email" type="tns:emailType"/>
<xs:element name="age" type="tns:ageType"/>复杂类型
complexType 可包含子元素和属性。sequence 强制顺序;choice 允许选其一;all 允许任意顺序(每个最多一次)。组合器可嵌套以表达丰富结构。
<xs:complexType name="AddressType">
<xs:sequence>
<xs:element name="street" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="zip" type="xs:string"/>
</xs:sequence>
<xs:attribute name="country" type="xs:string" default="US"/>
</xs:complexType>
<!-- Content model indicators: sequence, choice, all -->
<xs:complexType name="ContactType">
<xs:choice>
<xs:element name="phone" type="xs:string"/>
<xs:element name="email" type="xs:string"/>
</xs:choice>
</xs:complexType>内置类型
XSD 提供丰富的类型层次:字符串、数字(integer、decimal、float)、日期/时间、boolean、anyURI、ID/IDREF、QName。每个都支持 length、pattern、enumeration 等约束面做进一步限制。
<!-- Common XSD built-in types -->
<xs:element name="count" type="xs:integer"/>
<xs:element name="price" type="xs:decimal"/>
<xs:element name="flag" type="xs:boolean"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="date" type="xs:date"/> <!-- 2024-01-15 -->
<xs:element name="time" type="xs:time"/> <!-- 13:45:00 -->
<xs:element name="dt" type="xs:dateTime"/> <!-- 2024-01-15T13:45:00 -->
<xs:element name="id" type="xs:ID"/>
<xs:element name="ref" type="xs:IDREF"/>
<xs:element name="uri" type="xs:anyURI"/>约束(约束面)
约束面约束简单类型:enumeration(允许值)、pattern(正则)、length/minLength/maxLength、min/maxInclusive/Exclusive、totalDigits、fractionDigits、whiteSpace(preserve/replace/collapse)。
<xs:simpleType name="ColorType">
<xs:restriction base="xs:string">
<xs:enumeration value="red"/>
<xs:enumeration value="green"/>
<xs:enumeration value="blue"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PasswordType">
<xs:restriction base="xs:string">
<xs:minLength value="8"/>
<xs:maxLength value="32"/>
<xs:pattern value="[A-Za-z0-9!@#]+"/>
</xs:restriction>
</xs:simpleType>XSD 中的元素与属性
minOccurs/maxOccurs 控制基数(默认 1);maxOccurs='unbounded' 允许任意数量。属性 'use' 为 required/optional/prohibited,可带可选 default 或 fixed 值。匿名复杂类型内联定义。
<xs:element name="product">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"
minOccurs="1" maxOccurs="1"/>
<xs:element name="tag" type="xs:string"
minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="sku" type="xs:string" use="required"/>
<xs:attribute name="weight" type="xs:decimal" use="optional"
default="0.0"/>
</xs:complexType>
</xs:element>XPath
路径表达式
XPath 使用类路径表达式。'/' 从根选择;'//' 在任意深度选择后代。'*' 是任意元素的通配符;'@' 选择属性。以 '/' 开头的表达式是绝对的。
<!-- Sample: <bookstore><book><title>..</title></book></bookstore> -->
/bookstore/book/title <!-- absolute path -->
bookstore/book/title <!-- relative path -->
//title <!-- any title, anywhere -->
/bookstore//title <!-- title anywhere under bookstore -->
bookstore/* <!-- all children of bookstore -->
//@lang <!-- all lang attributes -->
//@* <!-- all attributes -->谓词
[ ] 中的谓词过滤节点集。索引从 1 开始。last() 和 position() 指节点在其上下文中的位置。谓词可测试元素文本、属性(@name)或计算值。
//book[1] <!-- first book -->
//book[last()] <!-- last book -->
//book[position() <= 3] <!-- first three books -->
//book[price > 25] <!-- books with price > 25 -->
//book[@category='web'] <!-- books in the web category -->
//book[author='Smith'] <!-- books authored by Smith -->
//book[@lang][2] <!-- 2nd book that has a lang attr -->轴
轴定义导航方向:child(默认)、descendant、parent(..)、ancestor、following-sibling、preceding-sibling、attribute(@)、self(.)、descendant-or-self(//)。多数有实践中常用的简写形式。
child::book <!-- default axis: children named book -->
descendant::title <!-- all title descendants -->
parent::* <!-- the parent element (shorthand: ..) -->
ancestor::section <!-- all section ancestors -->
following-sibling::p <!-- p elements after this one -->
preceding::item <!-- items before this in document order -->
attribute::id <!-- the id attribute (shorthand: @id) -->
self::node() <!-- the current node (shorthand: .) -->函数
XPath 1.0 内置函数:count、sum、string-length、contains、starts-with、normalize-space、name、concat、substring、round 等。XPath 2.0+ 大幅扩展函数库并增加类型。
count(//book) <!-- number of book elements -->
string-length(//title) <!-- length of first title's text -->
contains(//name, 'Ali') <!-- true if name contains 'Ali' -->
starts-with(@id, 'b') <!-- true if id starts with 'b' -->
normalize-space(//summary) <!-- collapse whitespace -->
name(//*[1]) <!-- name of the first element -->
concat(/a, /b) <!-- concatenate strings -->
sum(//price) <!-- sum of all price values -->运算符
XPath 用 = 表示相等(单个 =,不是 ==),用 'and'/'or' 做逻辑运算(不是 && / ||)。'div' 是除法,'mod' 是取模,因为 '/' 保留给路径。'|' 计算节点集的并集。
<!-- Comparison: =, !=, <, >, <=, >= -->
//book[price = 29.99]
//book[price < 20]
<!-- Logical: and, or -->
//book[price > 10 and price < 30]
//book[@cat='a' or @cat='b']
<!-- Arithmetic: + - * div mod -->
//item[price * quantity > 100]
5 div 2 <!-- 2.5 -->
5 mod 2 <!-- 1 -->
<!-- Union: | -->
//book | //magazineXPath 示例
这些模式组合路径、谓词和函数做实际查询。text() 选择文本节点;min() 需要 XPath 2.0+。带谓词的 //* 通配符是按属性在整个树中查找元素的常见方式。
<!-- Select all book titles priced over 20 -->
//book[price > 20]/title/text()
<!-- The category of the cheapest book -->
//book[price = min(//book/price)]/@category
<!-- Authors of books in the 'programming' category -->
//book[@category='programming']/author
<!-- Every 2nd item in each list -->
//list/item[position() mod 2 = 0]
<!-- Elements with a specific attribute value -->
//*[@lang='fr']XSLT 转换
基本转换
XSLT 样式表是 XML。模板用 XPath 匹配节点;apply-templates 递归处理选中的节点。value-of 提取文本。match='/' 模板最先在文档根上运行。
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Book List</h2>
<xsl:apply-templates select="bookstore/book"/>
</body>
</html>
</xsl:template>
<xsl:template match="book">
<p><xsl:value-of select="title"/> - <xsl:value-of select="price"/></p>
</xsl:template>
</xsl:stylesheet>xsl:template 与 apply-templates
匹配模板在处理器访问匹配节点时触发;命名模板用 call-template 显式调用。不带 select 的 apply-templates 处理所有子节点,实现递归的规则驱动转换。
<xsl:template match="book">
<div class="book">
<xsl:apply-templates select="title"/>
<xsl:apply-templates select="author"/>
</div>
</xsl:template>
<xsl:template match="title">
<h3><xsl:apply-templates/></h3>
</xsl:template>
<!-- named template (like a function) -->
<xsl:template name="divider">
<hr/>
</xsl:template>xsl:value-of 与 xsl:for-each
xsl:for-each 迭代节点集,改变上下文节点。对于扁平输出它常比模板简单,但过度使用会使样式表过程化。递归结构优先用模板和 apply-templates。