1

在 XSLT 2.0 转换中,我有 2 个输入:

拳头输入我的初始有效载荷:

<datas>
   <data1>1000</data1>
   <data2>2000</data2>
   <data3>1000</data3>
   <name1>1000</name1>
   <name2>1000</name2>
</datas>

第二个输入是转码服务的结果

<results>
  <result>
   <type>data<type>
   <key>1000</key>
   <value>john</value>
  <result>
  <result>
   <type>data<type>
   <key>2000</key>
   <value>tom</value>
  <result>
  <result>
   <type>name<type>
   <key>1000</key>
   <value>marc</value>
  <result>
  <result>
   <type>data<type>
   <key>1000</key>
   <value>john</value>
  <result>     
  <result>
   <type>name<type>
   <key>1000</key>
   <value>marc</value>
  <result>
 </results>

需要作为输出

<datas>
  <data1>john</data1>
  <data2>tom</data2>
  <data3>john</data3>
  <name1>marc</name1>
  <name2>marc</name2>
</datas>

想要创建一个 xslt 模板来映射响应,而无需每次都运行所有数据。结果顺序与输入数据不同

任何的想法 ?

问候

4

2 回答 2

1

您可以做的是首先匹配第一个 XML 文档中数据元素的子元素

<xsl:template match="datas/*">

然后将元素的“类型”和“位置”提取到变量中

<xsl:variable name="type" select="substring(local-name(), 1, 4)" />
<xsl:variable name="position" select="number(substring(local-name(), 5))" />

最后,您可以在第二个文档(在我的示例中将其称为“test2.xml”)中查找相关名称,如下所示:

<xsl:apply-templates select="document('test2.xml')/results/result[type=$type][position()=$position]/value/text()" />

这是完整的 XSLT

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

    <xsl:template match="datas/*">
        <xsl:variable name="type" select="substring(local-name(), 1, 4)" />
        <xsl:variable name="position" select="number(substring(local-name(), 5))" />
        <xsl:copy>
           <xsl:apply-templates select="document('test2.xml')/results/result[type=$type][position()=$position]/value/text()" />
        </xsl:copy>
    </xsl:template>

     <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

当应用于您的输入 XML 时,应输出以下内容

<datas>
   <data1>john</data1>
   <data2>tom</data2>
   <data3>john</data3>
   <name1>marc</name1>
   <name2>marc</name2>
</datas>

编辑:正如 Martin Honnen 在评论中正确指出的那样(谢谢 Martin!),这最好用钥匙来实现。首先像这样定义一个键:

 <xsl:key name="lookup" match="result" use="type" />

然后你可以像这样从第二个文档中查找文本:

<xsl:apply-templates
     select="key('lookup', $type, document('test2.xml'))[$position]/value/text()" />

这个 XSLT 也应该可以工作(在 XSLT 2.0 中)

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

    <xsl:key name="lookup" match="result" use="type" />

    <xsl:template match="datas/*">
        <xsl:variable name="type" select="substring(local-name(), 1, 4)" />
        <xsl:variable name="position" select="number(substring(local-name(), 5))" />
        <xsl:copy>
           <xsl:apply-templates
                select="key('lookup', $type, document('test2.xml'))[$position]/value/text()" />
        </xsl:copy>
    </xsl:template>

     <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
于 2013-03-29T16:02:36.007 回答
0

一个不依赖于位置的简短解决方案,不使用任何非全局变量

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kResByChildren" match="value"
  use="concat(../type, '+', ../key)"/>

 <xsl:variable name="vDocResults" select=
   "document('file:///c:/temp/delete/results.xml')"/>

 <xsl:template match="node()[not(self::text())]|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="text()">
  <xsl:value-of select=
  "key('kResByChildren', concat(substring(name(..),1,4), '+', .),
                                $vDocResults)[1]"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<datas>
   <data1>1000</data1>
   <data2>2000</data2>
   <data3>1000</data3>
   <name1>1000</name1>
   <name2>1000</name2>
</datas>

第二个提供的文档(已纠正所有畸形)位于文件中c:\temp\delete\results.xml

<results>
  <result>
   <type>data</type>
   <key>1000</key>
   <value>john</value>
  </result>
  <result>
   <type>data</type>
   <key>2000</key>
   <value>tom</value>
  </result>
  <result>
   <type>name</type>
   <key>1000</key>
   <value>marc</value>
  </result>
  <result>
   <type>data</type>
   <key>1000</key>
   <value>john</value>
  </result>
  <result>
   <type>name</type>
   <key>1000</key>
   <value>marc</value>
  </result>
 </results>

产生了想要的正确结果:

<datas>
   <data1>john</data1>
   <data2>tom</data2>
   <data3>john</data3>
   <name1>marc</name1>
   <name2>marc</name2>
</datas>

解释: 使用复合键。

于 2013-03-30T04:49:16.437 回答