【问题标题】:Printing the set of key-value pairs of data inside a XML element using XSLT使用 XSLT 打印 XML 元素内的一组键值对数据
【发布时间】:2010-11-05 06:36:39
【问题描述】:

对于给定的 XML 节点,我需要获取它的键值对。举个例子:

对于 XML:

<root>
    <detail1>
        <test1> Text1 </test1>
        <test2> Text2 </test2>
        <test3> Text3 </test3>
    </detail1>
    <detail2> description 1 </detail2>
    <detail3> description 2 </detail3>
</root>

我需要一个如下表(忽略最上面的元素):

详细信息1 |测试1:文本1 |测试2:文本2 |测试2:文本3 | 详情2 |说明 1 | 细节3 |说明 2

这对 XSLT 可行吗?如果有人能指出我的示例或资源,那将非常有用。

【问题讨论】:

  • 你想要什么格式的表格,HTML?
  • 是的,我需要一个 HTML 表格。
  • 好问题,+1。请参阅我的答案,以获得完全符合 XSLT 精神的完整而简短的解决方案(使用推送样式)。这是迄今为止唯一能准确产生所需输出的答案。

标签: java xml xslt


【解决方案1】:

这种转变

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vBlanks" select="'                         '"/>

 <xsl:template match="/*/*">
  <xsl:value-of select="concat('&#xA;', name(), ' | ')"/>
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="/*/*/*">
  <xsl:value-of select="concat(name(), ' : ')"/>
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="/*/*/*[not(position()=1)]">
  <xsl:text>&#xA;</xsl:text>
  <xsl:value-of select="substring($vBlanks,1,string-length(name(..))+1)"/>
  <xsl:value-of select="concat('| ', name(), ' : ')"/>
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<root>
    <detail1>
        <test1> Text1 </test1>
        <test2> Text2 </test2>
        <test3> Text3 </test3>
    </detail1>
    <detail2> description 1 </detail2>
    <detail3> description 2 </detail3>
</root>

产生想要的正确结果

detail1 | test1 :  Text1 
        | test2 :  Text2 
        | test3 :  Text3 
detail2 |  description 1 
detail3 |  description 2 

【讨论】:

    【解决方案2】:

    您应该查看Print XML tag names and values in Java。主要思想是name()和text()函数,构建格式应该比较容易

    【讨论】:

      【解决方案3】:

      是的。您需要 for-each 标记,它允许您循环 XPath 表达式的结果。

      请参阅 http://www.w3schools.com/xsl/xsl_for_each.asp 了解说明和用例。

      【讨论】:

        【解决方案4】:

        与使用 xsl:for-each 相比,我更喜欢使用 xsl:apply-templates。

        编辑:将匹配子句从 *[text()] 更改为 *[count(text()) = 1]

        如果你应用这个变换

        <?xml version="1.0"?>
        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        
          <xsl:template match="/">
            <html>
              <table>
                <xsl:apply-templates select="root/*"/>
              </table>
            </html>
          </xsl:template>
        
          <xsl:template match="*[count(text()) = 1]">
            <tr>
              <td>
                <xsl:value-of select="name()"/>
              </td>
              <td>
                <xsl:value-of select="."/>
              </td>
            </tr>
          </xsl:template>
        
          <xsl:template match="*">
            <xsl:apply-templates select="*" mode="keyvalue"/>
          </xsl:template>
        
          <xsl:template match="*" mode="keyvalue">
            <tr>
              <xsl:choose>
                <xsl:when test="position() = 1">
                  <td>
                    <xsl:value-of select="name(..)"/>
                  </td>
                  <td>
                    <xsl:call-template name="formatkeyvalue"/>
                  </td>
                </xsl:when>
                <xsl:otherwise>
                  <td></td>
                  <td>
                    <xsl:call-template name="formatkeyvalue"/>
                  </td>
                </xsl:otherwise>
              </xsl:choose>
            </tr>
          </xsl:template>
        
          <xsl:template name="formatkeyvalue">
            <xsl:value-of select="concat(name(), ' : ', text())"/>
          </xsl:template>
        
        </xsl:stylesheet>
        

        你的输入,你得到

        <html>
          <table>
            <tr>
              <td>detail1</td>
              <td>test1 :  Text1 </td>
            </tr>
            <tr>
              <td></td>
              <td>test2 :  Text2 </td>
            </tr>
            <tr>
              <td></td>
              <td>test3 :  Text3 </td>
            </tr>
            <tr>
              <td>detail2</td>
              <td> description 1 </td>
            </tr>
            <tr>
              <td>detail3</td>
              <td> description 2 </td>
            </tr>
          </table>
        </html>
        

        【讨论】:

        • 这正是我想要的。但是当我运行它时,生成的表缺少 test1、test2、test3 值。我对 xslt 很陌生。你能给我一个提示可能是什么问题吗?提前谢谢你。
        • @sunnyj:很奇怪。我用 Xselerator 开发了这个解决方案,它很有效(顺便说一句,很棒的工具)。阅读您的评论后,我在 Visual Studio 中重新测试了转换,但正如您所描述的那样失败了。有趣,但很烦人。我想我找到了导致它的原因并更新了我的答案。这个有用吗?
        【解决方案5】:

        这个样式表:

        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:template match="/*">
                <table border="1px">
                    <xsl:apply-templates/>
                </table>
            </xsl:template>
            <xsl:template match="/*/*">
                <tr>
                    <td>
                        <xsl:value-of select="name()"/>
                    </td>
                    <td>
                        <xsl:apply-templates/>
                    </td>
                </tr>
            </xsl:template>
            <xsl:template match="/*/*/*">
                <xsl:value-of select="concat(name(),' : ')"/>
                <xsl:apply-templates/>
                <xsl:if test="following-sibling::*">
                    <br/>
                </xsl:if>
            </xsl:template>
        </xsl:stylesheet>
        

        输出:

        <table border="1px">
            <tr>
                <td>detail1</td>
                <td>test1 :  Text1 
                    <br />test2 :  Text2 
                    <br />test3 :  Text3 
                </td>
            </tr>
            <tr>
                <td>detail2</td>
                <td> description 1 </td>
            </tr>
            <tr>
                <td>detail3</td>
                <td> description 2 </td>
            </tr>
        </table>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-30
          • 1970-01-01
          相关资源
          最近更新 更多