Как извлечь неизвестное количество элементов из сложного типа в XML? - PullRequest
0 голосов
/ 31 октября 2019

Это немного сбивает с толку слово, поэтому предположим, что у меня есть следующее в файле 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-файл, используя таблицу стилей xsl, используя <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">, которая будет отображать эту информацию в таблице, когда она преобразуется в 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 Ответ

1 голос
/ 31 октября 2019

Проблема, по которой ваш 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 , описанный в этом ответе SO , который заменяет строку NaN (не число) на 0. Это полезно, если указанный элемент не существует.

...