如何从xml中的复杂类型中检索未知数量的元素?

时间:2019-10-31 04:55:33

标签: xml xslt xsd xsd-validation

这有点让人难以理解,因此假设我在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时,它将在表格中显示该信息。由于每个家庭的信息都不相同,我将如何创建一个包含所有信息的表?该表将如下所示: enter image description here 更具体地说,我将如何使用xsl:for-each和类似的xsl元素来创建该表,特别是因为存在可选元素,并且您不知道该系列是如何制作的?

编辑:不得不将表从“爬行动物”重做为“蛇”“蜥蜴”

编辑:这是我要处理的示例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>
...

1 个答案:

答案 0 :(得分:1)

为什么带有{Family“选项的xsl:for-each无法正常工作的原因是上下文节点错误。模板选择了没有/元素的文档节点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(不是数字)。如果给定的元素不存在,这将很有用。