XSL: создать уникальную карту из дочерних узлов в нескольких файлах XML, а затем отобразить ее в таблице - PullRequest
2 голосов
/ 10 марта 2011

Используйте XSL для построения уникальной карты из дочерних узлов, а затем отобразите ее в таблице

Я хотел бы создать xsl, который принимает следующие XML-документы в качестве входных данных

Source.xml

<root>
<children>
<child>
Source-A
</child>
<child>
Source-B
</child>
</children>
</root>

Источник-a.xml

<child>
 <Objects>
  <Object>
   <Key>Key-1234</Key>
  </Object>
  <Object>
   <Key>Key-5678</Key>
  </Object>
 </Objects>
</child>

Источник-B.xml

<child>
 <Objects>
  <Object>
   <Key>Key-5678</Key>
  </Object>
  <Object>
   <Key>Key-ABCD</Key>
  </Object>
 </Objects>
</child>

и создает вывод html, который выглядит следующим образом.

<table border=1>
 <tr>
  <td>
   Key
  </td>
  <td>
   Key-1234
  </td>
  <tr>
  </tr>
  <td colspan="2">
   Source-A
  </td>
 </tr>

 <tr>
  <td>
   Key
  </td>
  <td>
   Key-5678
  </td>
  <tr>
  </tr>
  <td colspan="2">
   Source-A
   Source-B
  </td>
 </tr>

 <tr>
  <td>
   Key
  </td>
  <td>
   Key-ABCD
  </td>
  <tr>
  </tr>
  <td colspan="2">
   Source-B
  </td>
 </tr>

</table>

Вот что у меня пока есть, но я не уверен, что это вообще возможно, есть какие-нибудь намеки на то, как это сделать? Или я пытаюсь сделать что-то невозможное?

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">

  <xsl:template match="/">
    <html>
      <!--<xsl:variable name="keyMap" />-->
      <xsl:variable name="keyMap">
        <xsl:for-each select="root/children/child">
          <xsl:variable name="object" select="."/>
          <!--<xsl:value-of select="$object"/>-->
          <xsl:for-each select="document(concat(translate($object,'&#10;',''),'.xml'))/child/Objects/Object">
             <xsl:value-of select="Key"/>
          </xsl:for-each>
        </xsl:for-each>
      </xsl:variable>
      <xsl:value-of select="$keyMap"/>

    </html>
  </xsl:template>
</xsl:stylesheet>

1 Ответ

2 голосов
/ 10 марта 2011

Обновление : двухфазное преобразование с функцией расширения node-set().

Эта таблица стилей:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes="msxsl">
    <xsl:key name="kKeyByValue" match="Key" use="."/>
    <xsl:template match="/">
        <xsl:variable name="vFirstPass">
            <xsl:for-each select="root/children/child">
                <xsl:variable name="vSource" select="normalize-space()"/>
                <source href="{$vSource}">
                    <xsl:copy-of select="document(concat($vSource,'.xml'))
                                            /child/Objects/Object/Key"/>
                </source>
            </xsl:for-each>
        </xsl:variable>
        <table border="1">
            <xsl:apply-templates select="msxsl:node-set($vFirstPass)/*"/>
        </table>
    </xsl:template>
    <xsl:template match="text()"/>
    <xsl:template match="Key[count(.|key('kKeyByValue',.)[1]) = 1]">
        <tr>
            <td>Key</td>
            <td>
                <xsl:value-of select="."/>
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <xsl:for-each select="key('kKeyByValue',.)">
                    <xsl:value-of select="normalize-space(../@href)"/>
                    <xsl:if test="position()!=last()">
                        <xsl:text>&#x20;</xsl:text>
                    </xsl:if>
                </xsl:for-each>
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>

Выход:

<table border="1">
    <tr>
        <td>Key</td>
        <td>Key-1234</td>
    </tr>
    <tr>
        <td colspan="2">Source-A</td>
    </tr>
    <tr>
        <td>Key</td>
        <td>Key-5678</td>
    </tr>
    <tr>
        <td colspan="2">Source-A Source-B</td>
    </tr> 
    <tr>
        <td>Key</td>
        <td>Key-ABCD</td>
    </tr>
    <tr>
        <td colspan="2">Source-B</td>
    </tr>
</table>

Без расширений эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kChildByDocument"
             match="child"
             use="generate-id(
                     document(concat(normalize-space(),'.xml'),.)
                  )"/>
    <xsl:key name="kRootByKeys"
             match="/"
             use="child/Objects/Object/Key"/>
    <xsl:variable name="vSource" select="/"/>
    <xsl:template match="/" name="getDocuments">
        <xsl:param name="pDocuments" select="/.."/>
        <xsl:param name="pURIs" select="root/children/child"/>
        <xsl:choose>
            <xsl:when test="$pURIs">
                <xsl:call-template name="getDocuments">
                    <xsl:with-param name="pDocuments"
                     select="$pDocuments |
                             document(concat(normalize-space($pURIs[1]),
                                             '.xml'),
                                      .)"/>
                    <xsl:with-param name="pURIs"
                                    select="$pURIs[position()>1]"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <table border="1">
                    <xsl:call-template name="makeRows">
                        <xsl:with-param name="pDocuments"
                                        select="$pDocuments"/>
                    </xsl:call-template>
                </table>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template name="makeRows">
        <xsl:param name="pDocuments" select="/.."/>
        <xsl:param name="pKeys"
                   select="$pDocuments/child/Objects/Object/Key"/>
        <xsl:if test="$pKeys">
            <xsl:variable name="vKey" select="$pKeys[1]"/>
            <tr>
                <td>Key</td>
                <td>
                    <xsl:value-of select="$vKey"/>
                </td>
            </tr>
            <tr>
                <td colspan="2">
                    <xsl:for-each select="$pDocuments[
                                             key('kRootByKeys',$vKey)
                                          ]">
                        <xsl:variable name="vDocument"
                                      select="generate-id()"/>
                        <xsl:for-each select="$vSource">
                            <xsl:value-of
                                 select="normalize-space(
                                            key('kChildByDocument',
                                                $vDocument)
                                         )"/>
                        </xsl:for-each>
                        <xsl:if test="position()!=last()">
                            <xsl:text>&#x20;</xsl:text>
                        </xsl:if>
                    </xsl:for-each>
                </td>
            </tr>
            <xsl:call-template name="makeRows">
                <xsl:with-param name="pDocuments" select="$pDocuments"/>
                <xsl:with-param name="pKeys" select="$pKeys[.!=$vKey]"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...