XSL:从多个 xml 文件中的子节点构建唯一的映射,然后将其显示在表格中

发布于 2024-10-21 06:26:48 字数 2357 浏览 1 评论 0原文

使用 XSL 从子节点构建唯一的映射,然后将其显示在表中

我想创建一个 xsl,它将以下 xml 文档作为输入

Source.xml

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

Source-A.xml

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

Source-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>

Use XSL to build a unique map from child nodes, then display it in a table

I would like to create a xsl that takes the following xml documents as input

Source.xml

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

Source-A.xml

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

Source-B.xml

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

and creates some html output that looks like this.

<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>

Here is what I have so far, but I'm not sure it's even possible, any hints on how to do it? Or am I trying to do something thats not possible?

<?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,'
',''),'.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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你是暖光i 2024-10-28 06:26:48

更新:使用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> </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> </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>

Update: Two phase transformation with node-set() extension function.

This stylesheet:

<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> </xsl:text>
                    </xsl:if>
                </xsl:for-each>
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>

Output:

<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>

Without extensions, this stylesheet:

<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> </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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文