如何从 xml 中的复杂类型中检索未知数量的元素?
How to retrieve an unknown number of elements from a complex type in xml?
这有点令人困惑所以假设我在 xsd 文件中有以下内容(抱歉格式不佳或有错误,即时写下):
<?xml version = "1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="Family">
<xsd:sequence>
<xsd:element name="Person" type="xsd:string" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="Pets" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Dogs" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Cats" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Reptiles" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Snakes" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Lizards" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
<xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
并且假设我有一个 xml 文件是这样的一个实例:
...
<Family>
<Person>Father</Person>
<Person>Mother</Person>
<Person>Son</Person>
<Pets>
<Reptiles>
<Snakes>2</Snakes>
<Reptiles>
</Pets>
</Family>
<Family>
<Person>Father</Person>
<Person>Mother</Person>
<Person>Son</Person>
<Person>Daughter</Person>
<Pets>
<Dogs>1</Dogs>
</Pets>
</Family>
<Family>
<Person>Father</Person>
<Person>Mother</Person>
<Person>Daughter</Person>
<Pets>
<Cats>3</Cats>
</Pets>
</Family>
<Family>
<Person>Father</Person>
<Person>Mother</Person>
<Person>Son</Person>
<Person>Daughter</Person>
<Pets>
<Dogs>2</Dogs>
<Cats>3</Cats>
<Reptiles>
<Lizards>3</Lizards>
</Reptiles>
</Pets>
</Family>
...
我要使用 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
使用 xsl 样式表创建一个 xsl 文件,当它被转换为 html 时,它将在 table 中显示此信息。由于每个家庭的信息都不同,我将如何着手创建一个包含所有信息的 table? table 看起来像这样:
更具体地说,我将如何使用 xsl:for-each
和类似的 xsl 元素来得出 table 特别是因为有可选元素,而您事先不知道该系列是如何制作的?
编辑:不得不重做 table 从 "Reptiles" 到 "Snakes" "Lizards"
编辑:这是我正在尝试处理的示例 xsl 文件
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html><body>
<h1>Family Information</h1>
<table border="1">
<tr bgcolor="yellow">
<td><b>People</b></td>
<td><b>Dogs</b></td>
<td><b>Cats</b></td>
<td><b>Snakes</b></td>
<td><b>Lizards</b></td>
</tr>
<xsl:for-each select="Family">
<tr style="font-size: 11pt; font-family: verdana">
//How do I get the attribute values here?
</tr>
</xsl:for-each>
</table>
<body><html>
</xsl:template>
</xsl:stylesheet>
...
你的 xsl:for-each
和 "Family" select 不工作的问题是因为上下文节点是错误的。模板 selected 文档节点 /
没有 Family
元素作为子元素(因为 XML 中只允许有一个根节点)。所以 xsl:for-each
试图遍历一个空集。
为了解决这个问题,我添加了一个名为 <root>
的根节点来包装 <Family>
元素。所以示例 XML 文件如下所示:
<?xml-stylesheet href="transform.xslt" type="text/xsl" ?>
<root>
<Family>
...
</Family>
<Family>
...
</Family>
...
</root>
现在,您可以使用以下模板访问 <Family>
元素,这会产生所需的结果:
<xsl:template match="/root">
<html><body>
<h1>Family Information</h1>
<table border="1">
<tr bgcolor="yellow">
<td><b>People</b></td>
<td><b>Dogs</b></td>
<td><b>Cats</b></td>
<td><b>Snakes</b></td>
<td><b>Lizards</b></td>
</tr>
<xsl:for-each select="Family">
<tr>
<td><xsl:for-each select="Person"><xsl:value-of select="." /><xsl:if test="position() != last()">, </xsl:if></xsl:for-each></td>
<td><xsl:value-of select="translate(number(Pets/Dogs),'aN','0')" /></td>
<td><xsl:value-of select="translate(number(Pets/Cats),'aN','0')" /></td>
<td><xsl:value-of select="translate(number(Pets/Reptiles/Snakes),'aN','0')" /></td>
<td><xsl:value-of select="translate(number(Pets/Reptiles/Lizards),'aN','0')" /></td>
</tr>
</xsl:for-each>
</table>
</body></html>
</xsl:template>
translate(number(Pets/...),'aN','0')
是一种聪明的 XSLT-1.0 方式 described in this SO answer,它将字符串 NaN
(不是数字)替换为 0
。如果给定的元素不存在,这很有用。
这有点令人困惑所以假设我在 xsd 文件中有以下内容(抱歉格式不佳或有错误,即时写下):
<?xml version = "1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="Family">
<xsd:sequence>
<xsd:element name="Person" type="xsd:string" minOccurs="1" maxOccurs="unbounded"/>
<xsd:element name="Pets" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Dogs" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Cats" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Reptiles" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Snakes" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="Lizards" type="xsd:int" minOccurs="0" maxOccurs="unbounded"/>
<xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
并且假设我有一个 xml 文件是这样的一个实例:
...
<Family>
<Person>Father</Person>
<Person>Mother</Person>
<Person>Son</Person>
<Pets>
<Reptiles>
<Snakes>2</Snakes>
<Reptiles>
</Pets>
</Family>
<Family>
<Person>Father</Person>
<Person>Mother</Person>
<Person>Son</Person>
<Person>Daughter</Person>
<Pets>
<Dogs>1</Dogs>
</Pets>
</Family>
<Family>
<Person>Father</Person>
<Person>Mother</Person>
<Person>Daughter</Person>
<Pets>
<Cats>3</Cats>
</Pets>
</Family>
<Family>
<Person>Father</Person>
<Person>Mother</Person>
<Person>Son</Person>
<Person>Daughter</Person>
<Pets>
<Dogs>2</Dogs>
<Cats>3</Cats>
<Reptiles>
<Lizards>3</Lizards>
</Reptiles>
</Pets>
</Family>
...
我要使用 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
使用 xsl 样式表创建一个 xsl 文件,当它被转换为 html 时,它将在 table 中显示此信息。由于每个家庭的信息都不同,我将如何着手创建一个包含所有信息的 table? table 看起来像这样:
xsl:for-each
和类似的 xsl 元素来得出 table 特别是因为有可选元素,而您事先不知道该系列是如何制作的?
编辑:不得不重做 table 从 "Reptiles" 到 "Snakes" "Lizards"
编辑:这是我正在尝试处理的示例 xsl 文件
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html><body>
<h1>Family Information</h1>
<table border="1">
<tr bgcolor="yellow">
<td><b>People</b></td>
<td><b>Dogs</b></td>
<td><b>Cats</b></td>
<td><b>Snakes</b></td>
<td><b>Lizards</b></td>
</tr>
<xsl:for-each select="Family">
<tr style="font-size: 11pt; font-family: verdana">
//How do I get the attribute values here?
</tr>
</xsl:for-each>
</table>
<body><html>
</xsl:template>
</xsl:stylesheet>
...
你的 xsl:for-each
和 "Family" select 不工作的问题是因为上下文节点是错误的。模板 selected 文档节点 /
没有 Family
元素作为子元素(因为 XML 中只允许有一个根节点)。所以 xsl:for-each
试图遍历一个空集。
为了解决这个问题,我添加了一个名为 <root>
的根节点来包装 <Family>
元素。所以示例 XML 文件如下所示:
<?xml-stylesheet href="transform.xslt" type="text/xsl" ?>
<root>
<Family>
...
</Family>
<Family>
...
</Family>
...
</root>
现在,您可以使用以下模板访问 <Family>
元素,这会产生所需的结果:
<xsl:template match="/root">
<html><body>
<h1>Family Information</h1>
<table border="1">
<tr bgcolor="yellow">
<td><b>People</b></td>
<td><b>Dogs</b></td>
<td><b>Cats</b></td>
<td><b>Snakes</b></td>
<td><b>Lizards</b></td>
</tr>
<xsl:for-each select="Family">
<tr>
<td><xsl:for-each select="Person"><xsl:value-of select="." /><xsl:if test="position() != last()">, </xsl:if></xsl:for-each></td>
<td><xsl:value-of select="translate(number(Pets/Dogs),'aN','0')" /></td>
<td><xsl:value-of select="translate(number(Pets/Cats),'aN','0')" /></td>
<td><xsl:value-of select="translate(number(Pets/Reptiles/Snakes),'aN','0')" /></td>
<td><xsl:value-of select="translate(number(Pets/Reptiles/Lizards),'aN','0')" /></td>
</tr>
</xsl:for-each>
</table>
</body></html>
</xsl:template>
translate(number(Pets/...),'aN','0')
是一种聪明的 XSLT-1.0 方式 described in this SO answer,它将字符串 NaN
(不是数字)替换为 0
。如果给定的元素不存在,这很有用。