XML-XSLT-在<xsl:for-each>

时间:2018-07-25 21:53:47

标签: xml xslt saxon xslt-3.0

我需要有关XSLT的帮助...

我有以下XML输入文档:

<?xml version="1.0" encoding="UTF-8"?>
<report xmlns="http://jasperreports.sourceforge.net/jasperreports" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" 
        repName="FirstElementTemp" 
        date="10-05-2001">
    <element1>
        <![CDATA[]]>
    </element1>
    <element2 name="secondElement"/>
    <head>
        <hText x="10" y="20">
            <textVal>TEXT 1</textVal>
        </hText>
        <hText x="10" y="30">
            <textVal>TEXT 2</textVal>
        </hText>
        <hText x="10" y="40">
            <textVal>TEXT 3</textVal>
        </hText>
    </head>
    <body/>
</report>

我正在尝试使用以下XSLT样式表对其进行转换:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xpath-default-namespace="http://jasperreports.sourceforge.net/jasperreports"
  xmlns:jsp="http://jasperreports.sourceforge.net/jasperreports"
  xmlns="http://jasperreports.sourceforge.net/jasperreports"
  exclude-result-prefixes="xs jsp"
  expand-text="yes"
  version="3.0">


<xsl:param name="doc2"  xmlns="">
    <secondDoc>
    <elementTemps>
        <elemTemp ID="1" name="FirstElementTemp" />
        <elemTemp ID="2" name="SecondTemplate" />
    </elementTemps>
    <elementReps>
        <elemRep tmpID="1" name="FirstElementRep" >
            <value forCDATA="THIS IS THE VALUE FOR CDATA 1">FIRST DATA 1</value>
            <value forCDATA="THIS IS THE VALUE FOR CDATA 1">FIRST DATA 2</value>
            <value forCDATA="THIS IS THE VALUE FOR CDATA 1">FIRST DATA 3</value>
        </elemRep>
        <elemRep tmpID="2" name="SecondTemplate">
            <value forCDATA="THIS IS THE VALUE FOR CDATA 2">SECOND DATA</value>
        </elemRep>
    </elementReps>
    </secondDoc>     
  </xsl:param>

<xsl:output indent="yes" cdata-section-elements="element1"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:key name="key1" match="elemTemp" use="@name" xpath-default-namespace=""/>
  <xsl:key name="key2" match="elemRep" use="@tmpID" xpath-default-namespace=""/>

 <xsl:template match="report/*[1]">
    <xsl:variable name="temp" select="key('key1', ../@repName, $doc2)"/>
    <xsl:variable name="rep" select="key('key2', $temp/@ID, $doc2)"/>
    <valueIs>
        <xsl:value-of select="$rep/value[1]" xpath-default-namespace=""/>
    </valueIs>
    <element1>
        <xsl:value-of select="$rep/value[1]/@forCDATA" xpath-default-namespace=""/>
    </element1>
</xsl:template> 

<xsl:template match="element2">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
            <newChild>THIS IS THE NEW CHILD</newChild>
    </xsl:copy>
</xsl:template>

<xsl:template match="report/body">
       <xsl:variable name="temp2" select="key('key1', ancestor::report/@repName, $doc2)"/>
      <xsl:variable name="rep2" select="key('key2', $temp2/@ID, $doc2)"/>
     <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:for-each select="$rep2/value" xpath-default-namespace="">
        <xsl:variable name="vCount" select="count(preceding-sibling::value)+1"/>
            <bText>
                    <xsl:attribute name="x">
                        <xsl:value-of select="/report/head/hText[$vCount]/@x"/>
                    </xsl:attribute>
                    <xsl:attribute name="y">
                        <xsl:value-of select="/report/head/hText[$vCount]/@y"/>
                    </xsl:attribute>
                    <textVal>
                        <xsl:value-of select="current()"/>
                    </textVal>
            </bText>
        </xsl:for-each>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

如您所见,我正在使用第二个XML输入文档(doc2),该文档以<xsl:param>的形式传递给XSLT。 XSLT样式表中不起作用的部分是最后一个<xsl:tempplate><xsl:template match="report/body">

基本上,这是我想要的输出:

<?xml version="1.0" encoding="UTF-8"?>
<report xmlns="http://jasperreports.sourceforge.net/jasperreports"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
        repName="FirstElementTemp"
        date="10-05-2001">
    <valueIs>FIRST DATA 1</valueIs>
   <element1><![CDATA[THIS IS THE VALUE FOR CDATA 1]]></element1>
    <element2 name="secondElement">
      <newChild>THIS IS THE NEW CHILD</newChild>
   </element2>
    <head>
        <hText x="10" y="20">
            <textVal>TEXT 1</textVal>
        </hText>
        <hText x="10" y="30">
            <textVal>TEXT 2</textVal>
        </hText>
        <hText x="10" y="40">
            <textVal>TEXT 3</textVal>
        </hText>
    </head>
    <body>
      <bText x="10" y="20">
         <textVal>FIRST DATA 1</textVal>
      </bText>
      <bText x="10" y="30">
         <textVal>FIRST DATA 2</textVal>
      </bText>
      <bText x="10" y="40">
         <textVal>FIRST DATA 3</textVal>
      </bText>
   </body>
</report>

但这是我真正得到的输出:

<?xml version="1.0" encoding="UTF-8"?>
<report xmlns="http://jasperreports.sourceforge.net/jasperreports"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
        repName="FirstElementTemp"
        date="10-05-2001">
    <valueIs>FIRST DATA 1</valueIs>
   <element1><![CDATA[THIS IS THE VALUE FOR CDATA 1]]></element1>
    <element2 name="secondElement">
      <newChild>THIS IS THE NEW CHILD</newChild>
   </element2>
    <head>
        <hText x="10" y="20">
            <textVal>TEXT 1</textVal>
        </hText>
        <hText x="10" y="30">
            <textVal>TEXT 2</textVal>
        </hText>
        <hText x="10" y="40">
            <textVal>TEXT 3</textVal>
        </hText>
    </head>
    <body>
      <bText x="" y="">
         <textVal>FIRST DATA 1</textVal>
      </bText>
      <bText x="" y="">
         <textVal>FIRST DATA 2</textVal>
      </bText>
      <bText x="" y="">
         <textVal>FIRST DATA 3</textVal>
      </bText>
   </body>
</report>

如您所见,我无法从<xsl:value-of select="/report/head/hText[$vCount]/@x"/><xsl:value-of select="/report/head/hText[$vCount]/@y"/>获取值,无法将{{的xy属性放入1}}个元素。

我认为这是因为在<bText>中进入第二个XML输入文档(<xsl:for-each>),然后在doc2元素中尝试返回第一个XML输入文件。另外,我正在使用<xsl:value-of>函数,因此可以确认我在第二个输入XML文档(current())的上下文中。

所以我需要做的是将名称空间改回doc2或将上下文更改为第一个输入XML文档的上下文。

我该怎么做?我尝试做"http://jasperreports.sourceforge.net/jasperreports"是因为我在<xsl:value-of select="/jsp:report/jsp:head/jsp:hText[$vCount]/@x"/>元素中定义了该命名空间,但是它没有用。

XSLT FIDDLE AT: https://xsltfiddle.liberty-development.net/94hvTzn

谢谢!

Alexandre Jacinto

1 个答案:

答案 0 :(得分:0)

将主输入文档存储在变量中,并确保将xpath默认名称空间切换回需要的位置:

    <xsl:variable name="main-doc" select="/"/>
    <xsl:for-each select="$rep2/value" xpath-default-namespace="">
        <xsl:variable name="vCount" select="position()"/>
        <bText xsl:xpath-default-namespace="http://jasperreports.sourceforge.net/jasperreports">
                <xsl:attribute name="x">
                    <xsl:value-of select="$main-doc/report/head/hText[$vCount]/@x"/>
                </xsl:attribute>
                <xsl:attribute name="y">
                    <xsl:value-of select="$main-doc/report/head/hText[$vCount]/@y"/>
                </xsl:attribute>
                <textVal>
                    <xsl:value-of select="current()"/>
                </textVal>
        </bText>
    </xsl:for-each>

https://xsltfiddle.liberty-development.net/94hvTzn/1

最后,在样式表中为主要输入元素声明名称空间前缀,然后在需要时使用它们来选择或匹配它们,然后在辅助输入文档中不使用前缀,可能会更容易。