XML - XSLT - 更改 <xsl:for-each> 中的名称空间上下文

XML - XSLT - Changing the namespace context inside <xsl:for-each>

我需要一些 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 属性<bText>个元素,分别为

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

的上下文中

所以我需要做的是将命名空间改回 "http://jasperreports.sourceforge.net/jasperreports" 或将上下文更改为第一个输入 XML 文档的上下文。

我该怎么做?我尝试执行 <xsl:value-of select="/jsp:report/jsp:head/jsp:hText[$vCount]/@x"/>,因为我在 <xsl:stylesheet> 元素中定义了该命名空间,但它不起作用。

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

谢谢!

亚历山大·哈辛托

将主要输入文档存储在一个变量中,并确保在需要的地方切换回 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

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