XML столбцы таблицы расположены вертикально в строках - PullRequest
0 голосов
/ 29 февраля 2020

Получена следующая проблема касательно отображения нескольких строк (таблиц) XML. Они (XML данные) оформлены в виде таблицы (как будто предполагается, что она будет отображаться в виде HTML таблицы). Самый обычный показанный способ - в виде HTML таблицы.

Но теперь способ, которым я хотел отображаться (через XSLT), похож на какую-то «карточку» со сворачиванием всех столбцов в строки, где количество строк должно быть равно количеству полей плюс одинаковое количество соответствующих заголовков.

Я покажу вам пример, чтобы лучше понять мои требования (этот вопрос уже поднимался ранее, но ни один из ответов не был удовлетворительным .. по крайней мере, не для меня). Вот моя таблица данных. xml:

<persns> 
 <prsn> 
  <fname>Smith</fname> 
  <lname>Milton</lname> 
  <age>44</age> 
  <addrss>5th summer st, mntb</addrss>
  <city>Portland</city>
 </prsn>
 <prsn> 
  <fname>Ken</fname> 
  <lname>Jackson</lname> 
  <age>37</age> 
  <addrss>19th Penfield ave, brtcl</addrss>
  <city>Kelowna</city>
 </prsn>
 <prsn> 
  <fname>Susan</fname> 
  <lname>Arkland</lname> 
  <age>48</age> 
  <addrss>34th Mansfield st, sgtp</addrss>
  <city>Raleigh</city>
 </prsn>
<persns>

, которая приблизительно может быть представлена ​​следующим образом:

|======|========|=====|======================|==========|
|FNAME | LNAME  | AGE |        ADDRESS       |   CITY   |
|======|========|=====|======================|==========|
|Smith |Milton  | 44  |  5th smmr st, mntb   | Portland |
|------|--------|-----|----------------------|----------|
| Ken  |Jackson | 37  |19th Pnfeld ave, brtcl| Kelowna  |
|------|--------|-----|----------------------|----------|
|Susan |Arkland | 48  |34th Mansfield st,sgtp| Raleigh  |
|------|--------|-----|----------------------|----------|
|Patsy |Brighton| 35  |12th Peel st, pnslv   |Phldlphia |
|======|========|=====|======================|==========|
                      Fig.1

И через какое-то преобразование .xslt мне понадобится xml чтобы отображаться так:

  |================|    |================|
  |      FNAME     |    |     FNAME      |  <--- header name   
  |----------------|    |----------------|
  |      Smith     |    |      Ken       |  <--- corresponding element name
  |----------------|    |----------------|
  |     LNAME      |    |     LNAME      |  <--- header name
  |----------------|    |----------------|
  |     Milton     |    |    Jackson     |  <--- corresponding element name
  |----------------|    |----------------|                                        . . . and so on
  |       AGE      |    |      AGE       |
  |----------------|    |----------------|
  |       44       |    |      37        |
  |----------------|    |----------------|
  |     ADDRESS    |    |    ADDRESS     |
  |----------------|    |----------------|
  |5th smmr st,mntb|    | 9th Pnfeld ave,|
  |----------------|    |----------------|
  |      CITY      |    |      CITY      |
  |----------------|    |----------------|
  |    Portland    |    |    Kelowna     |
  |================|    |================|
                    Fig.2

Как можно заметить, это отображение сначала с заголовком, затем с узлом элемента прямо под ним, затем со следующим заголовком, и снова под ним идет соответствующий элемент узла и так далее. Следующая таблица HTML снова строится сначала с заголовком сверху, затем с этим элементом узла и так далее, и так далее. И каждый из этих блоков элементов - с соответствующими заголовками - должен быть разделен на HTML таблиц (отдельно).

Будучи новичком в .xslt, я действительно не мог придумать, как это сделать, хотя я "сделал" какой-то плохой .xslt-код, который я опишу здесь. Но не работает вообще. Это дает что-то, но не настолько, как я хочу. Итак, вот оно:

<xsl:template match="/">
 <xsl:variable name="hd_tbl">
  <head fname ="FNAME" lnme="LNAME" age="AGE" addrs="ADDRESS" oras="oras"/>
 </xsl:variable>

  <xsl:for-each select="persns/prsn | $hd_tbl/head/@*"> 
     <table id="tbl" border="1"> 
 <xsl:choose>
  <xsl:when test="(position() mod 2) != 1"> <!-- even line -->
     <tr> <th> <xsl:value-of select="./@*"/></th></tr>
  </xsl:when>
  <xsl:otherwise>
    <tr> <td> <xsl:value-of select="."/></td></tr>
  </xsl:otherwise>
 </xsl:choose>
  </table>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Итак, ребята, пожалуйста, помогите мне разобраться с этим, так как я боролся с этим уже довольно давно.

Большое спасибо заранее.

Ответы [ 2 ]

2 голосов
/ 29 февраля 2020

Если вы используете гибкий контейнер для таблиц, вы можете определить остальную часть внешнего вида с помощью CSS:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    expand-text="yes"
    version="3.0">

  <xsl:output method="html" indent="yes" html-version="5"/>

  <xsl:template match="persns">
      <div class="box">
          <xsl:apply-templates/>
      </div>
  </xsl:template>

  <xsl:template match="prsn">
      <table>
          <tbody>
              <xsl:apply-templates/>
          </tbody>
      </table>
  </xsl:template>

  <xsl:template match="prsn/*">
      <tr>
          <th>{upper-case(local-name())}</th>
      </tr>
      <tr>
          <td>{.}</td>
      </tr>
  </xsl:template>

  <xsl:template match="/" expand-text="no">
    <html>
      <head>
        <title>.NET XSLT Fiddle Example</title>
        <style>
            .box { 
              display: flex; 
            }
            .box table {
              margin-right: 1em;
              border-collapse: collapse;
              border: 1px solid black;
            }
            .box table tr, .box table td, .box table th { 
              border: 1px solid black;
            }
            .box table td, .box table th {
              text-align: center;
            }
        </style>
      </head>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/pPJ9hEA

2 голосов
/ 29 февраля 2020

Предполагая, что ваш ввод регулярный (т.е. каждая запись имеет одинаковые поля в одинаковом порядке), вы можете сделать:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:template match="/persns">
    <xsl:variable name="records" select="prsn"/>
    <table border="1">
        <xsl:for-each select="prsn[1]/*">
            <xsl:variable name="field-name" select="name()"/>
            <xsl:variable name="i" select="position()"/>
            <tr>
                <xsl:for-each select="$records">
                    <th>
                        <xsl:value-of select="$field-name"/>
                    </th>
                </xsl:for-each>
            </tr>   
            <tr>
                <xsl:for-each select="$records">
                    <td>
                        <xsl:value-of select="*[$i]"/>
                    </td>
                </xsl:for-each>
            </tr>
        </xsl:for-each>
    </table>
</xsl:template>

</xsl:stylesheet>

, чтобы выдает результат:

<table border="1">
  <tr>
    <th>fname</th>
    <th>fname</th>
    <th>fname</th>
  </tr>
  <tr>
    <td>Smith</td>
    <td>Ken</td>
    <td>Susan</td>
  </tr>
  <tr>
    <th>lname</th>
    <th>lname</th>
    <th>lname</th>
  </tr>
  <tr>
    <td>Milton</td>
    <td>Jackson</td>
    <td>Arkland</td>
  </tr>
  <tr>
    <th>age</th>
    <th>age</th>
    <th>age</th>
  </tr>
  <tr>
    <td>44</td>
    <td>37</td>
    <td>48</td>
  </tr>
  <tr>
    <th>addrss</th>
    <th>addrss</th>
    <th>addrss</th>
  </tr>
  <tr>
    <td>5th summer st, mntb</td>
    <td>19th Penfield ave, brtcl</td>
    <td>34th Mansfield st, sgtp</td>
  </tr>
  <tr>
    <th>city</th>
    <th>city</th>
    <th>city</th>
  </tr>
  <tr>
    <td>Portland</td>
    <td>Kelowna</td>
    <td>Raleigh</td>
  </tr>
</table>

, который будет отображаться как одна таблица со столбцом для каждой записи и двойной строкой имени / значения для каждого поля:

enter image description here


PS Я не уверен, что диктует форму требуемого выхода. Лично я предпочел бы сделать:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:template match="/persns">
    <xsl:variable name="records" select="prsn"/>
    <table border="1">
        <xsl:for-each select="prsn[1]/*">
            <xsl:variable name="i" select="position()"/>
            <tr>
                <th>
                    <xsl:value-of select="name()"/>
                </th>
                <xsl:for-each select="$records">
                    <td>
                        <xsl:value-of select="*[$i]"/>
                    </td>
                </xsl:for-each>
            </tr>
        </xsl:for-each>
    </table>
</xsl:template>

</xsl:stylesheet>

, чтобы получить простую транспонированную (сводную) таблицу:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...