xslt,尝试创建标题行结构

kyvafyod  于 2021-07-26  发布在  Java
关注(0)|答案(3)|浏览(363)

这不是浏览器类型xslt,而是用于处理数据(sapb1集成框架)。假设我们有两个sql表,header和line,我们希望避免这样的工作:首先从header中选择,然后为每一行启动一个单独的select,因为这需要“可视化编程”,我们更喜欢编写代码而不是连接箭头。因此,我们向服务器发送一个查询,比如selectfrom header,selectfrom lines,我们得到一个大致如下的xml:

<ResultSets>
<ResultSet>
    <Row><MHeaderNum>1</MHeaderNum></Row>
    <Row><MHeaderNum>2</MHeaderNum></Row>
    <Row><MHeaderNum>3</MHeaderNum></Row>
</ResultSet>

<ResultSet>
    <Row><LineNum>1</LineNum> <HeaderNum>1</HeaderNum></Row>
    <Row><LineNum>2</LineNum> <HeaderNum>2</HeaderNum></Row>
    <Row><LineNum>1</LineNum> <HeaderNum>3</HeaderNum></Row>
    <Row><LineNum>2</LineNum> <HeaderNum>1</HeaderNum></Row>
    <Row><LineNum>1</LineNum> <HeaderNum>2</HeaderNum></Row>
    <Row><LineNum>2</LineNum> <HeaderNum>3</HeaderNum></Row>
</ResultSet>

所以我们认为我们是命令式的,程序式的程序员

<xsl:for-each select="//ResultSets/Resultset[1]/Row">
   do stuff with header data
   <xsl:for-each select="//ResultSets/Resultset[2]/Row[HeaderNum=MHeaderNum]">
      do stiff with the line data beloning to this particular header
   </xsl:for-each>  
</xsl:for-each>

当然,这是行不通的,因为mheadernum脱离了上下文,就像grunge过时了一样,我们也不能将它保存到变量中,因为我们不会更新这个变量,因为xslt是某种不可变的函数式编程语言。
但是不要害怕,一个内心的声音说,因为xsltMaven可以用模板解决类似的问题。如果我理解的话,模板是xslt的一种功能。它们可以是递归的之类的。那么它们能用来解决这样的问题吗?
当然,我们谈论的是XSLT1.0,因为我不知道java是否曾经费心实现过更高版本,但是sap当然没有费心使用假设的实现。
或者我真的应该忘记这一点,只是连接我的视觉箭头?问题是,sql不应该用在这样的遍历头然后遍历行的方式中。我想做的是让一个sql数据库开心起来,从中获取一大块数据,然后在其他地方处理它,而不是用七千万个小查询来打扰它。在我们的例子中,另一个地方是令人遗憾的xslt,虽然技术上我可以尝试javascript,而且sap也为这堆混乱添加了一个nashorn,但是也许它可以用“纯”xsl解决?

ct2axkht

ct2axkht1#

不管是xslt 1还是更高版本,也不管是使用模板还是针对每个模板 current() 函数存在: //ResultSets/Resultset[2]/Row[HeaderNum=current()/MHeaderNum] .

xqk2d5yq

xqk2d5yq2#

解决交叉引用的最佳方法是使用键。
例如,以下样式表:
xslt 1.0版

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

<xsl:key name="line-by-header" match="ResultSet[2]/Row" use="HeaderNum" />

<xsl:template match="/ResultSets">
    <output>    
        <xsl:for-each select="ResultSet[1]/Row">
            <header num="{MHeaderNum}"> 
                <xsl:for-each select="key('line-by-header', MHeaderNum)">
                    <line>
                        <xsl:value-of select="LineNum"/>
                    </line>
                </xsl:for-each>
            </header>
        </xsl:for-each>
    </output>
</xsl:template>

</xsl:stylesheet>

当应用于以下输入时:
xml格式

<ResultSets>
    <ResultSet>
        <Row><MHeaderNum>1</MHeaderNum></Row>
        <Row><MHeaderNum>2</MHeaderNum></Row>
        <Row><MHeaderNum>3</MHeaderNum></Row>
    </ResultSet>
    <ResultSet>
        <Row><LineNum>1</LineNum> <HeaderNum>1</HeaderNum></Row>
        <Row><LineNum>2</LineNum> <HeaderNum>2</HeaderNum></Row>
        <Row><LineNum>3</LineNum> <HeaderNum>3</HeaderNum></Row>
        <Row><LineNum>4</LineNum> <HeaderNum>1</HeaderNum></Row>
        <Row><LineNum>5</LineNum> <HeaderNum>2</HeaderNum></Row>
        <Row><LineNum>6</LineNum> <HeaderNum>3</HeaderNum></Row>
    </ResultSet>
</ResultSets>

将返回:
结果

<?xml version="1.0" encoding="UTF-8"?>
<output>
  <header num="1">
    <line>1</line>
    <line>4</line>
  </header>
  <header num="2">
    <line>2</line>
    <line>5</line>
  </header>
  <header num="3">
    <line>3</line>
    <line>6</line>
  </header>
</output>
tvokkenx

tvokkenx3#

您可以尝试以下xslt。它使用三个xslt模板。
因为所需的输出是未知的,所以我为每个标题和行项目模板放置了一些任意处理。
xslt

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

    <xsl:template match="/">
        <root>
            <xsl:apply-templates/>
        </root>
    </xsl:template>

    <xsl:template match="/ResultSets/ResultSet[1]">
        <ResultSet1>
            <xsl:for-each select="Row">
                <r>
                    <xsl:value-of select="MHeaderNum"/>
                </r>
            </xsl:for-each>
        </ResultSet1>
    </xsl:template>

    <xsl:template match="/ResultSets/ResultSet[2]">
        <ResultSet2>
            <xsl:for-each select="Row">
                    <xsl:copy-of select="."/>
            </xsl:for-each>
        </ResultSet2>
    </xsl:template>
</xsl:stylesheet>

相关问题