如何从 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。如果给定的元素不存在,这很有用。