如何使用XSLT从同级元素中的内容插入新元素

时间:2019-04-11 14:49:54

标签: xml xslt xpath

我有一些现有的XML输出,我需要在其中插入一个新元素,其中将包含一些硬编码数据和一些动态数据,这些数据是从两个同级元素的值派生的。

我已经尝试了多次迭代,但是无法获得任何有意义的输出结果

XML输入:

<ExportXML xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07" 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:ns1="http://www.taleo.com/ws/integration/toolkit/2005/07" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <record>
                <field name="Client">Company X</field>
                <field name="TItle">Program Manager</field>
                <field name="ReqNumber">106839</field>
                <field name="JobBoardID">JB-10000</field>
                <field name="PostedDate">2019-04-03</field>
                <field name="City"></field>
                <field name="StateProvince"></field>
                <field name="Country">United States</field>
                <field name="Category">Professionals</field>
                <field name="JobText">Blah, blah, blah</field>
            </record>
            <record>
                <field name="Client">Company X</field>
                <field name="TItle">Director, Sales--Army</field>
                <field name="ReqNumber">106051</field>
                <field name="JobBoardID">JB-13262</field>
                <field name="PostedDate">2019-03-04</field>
                <field name="City"></field>
                <field name="StateProvince"></field>
                <field name="Country">United States</field>
                <field name="Category">Sales Workers</field>
                <field name="JobText">Blah, blah, blah</field>
            </record>
</ExportXML>

所需的XML输出:

<ExportXML xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07" 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:ns1="http://www.taleo.com/ws/integration/toolkit/2005/07" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <record>
                <field name="Client">Company X</field>
                <field name="TItle">Program Manager</field>
                <field name="ReqNumber">106839</field>
                <field name="JobBoardID">JB-10000</field>
                <field name="PostedDate">2019-04-03</field>
                <field name="City"></field>
                <field name="StateProvince"></field>
                <field name="Country">United States</field>
                <field name="Category">Professionals</field>
                <field name="JobText">Blah, blah, blah</field>
                <field name="ApplyURL">https://www.fakedomain.org/careersection/JB-10000/jobapply.ftl?lang=en&amp;job=106839</field>
            </record>
            <record>
                <field name="Client">Company X</field>
                <field name="TItle">Director, Sales--Army</field>
                <field name="ReqNumber">106051</field>
                <field name="JobBoardID">JB-13262</field>
                <field name="PostedDate">2019-03-04</field>
                <field name="City"></field>
                <field name="StateProvince"></field>
                <field name="Country">United States</field>
                <field name="Category">Sales Workers</field>
                <field name="JobText">Blah, blah, blah</field>
                <field name="ApplyURL">https://www.fakedomain.org/careersection/JB-13262/jobapply.ftl?lang=en&amp;job=106051</field>
            </record>
</ExportXML>

如您在上面的代码示例中所看到的,我想添加一个新的“ field”元素,其属性为“ ApplyURL”,该属性采用硬编码字符串(https://www.fakedomain.org/careersection/),并将其与具有“ JobBoardID”属性的同级字段元素,将其与“ /jobapply.ftl?lang=en&job=“的硬编码字符串连接起来,并与具有“ ReqNumber”属性的同级字段元素的值连接。

我需要将此模板规则应用于XML文档中找到的所有“记录”节点。

我为此尝试了各种方法,但是到目前为止还没有成功。我是XSLT的新手,所以并不奇怪。我希望对此有更丰富经验的人可以帮助我。

2 个答案:

答案 0 :(得分:1)

考虑使用concat构建URL,以获取硬编码和动态数据。确保为XSLT分配一个名称空间前缀,例如以下使用 doc 的名称,因为原始输入XML会保留一个默认的名称空间:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
               xmlns:doc="http://www.taleo.com/ws/integration/toolkit/2005/07" > 
   <xsl:output version="1.0" encoding="UTF-8" indent="yes" />
   <xsl:strip-space elements="*"/>

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

   <!-- rewrite record node -->
   <xsl:template match="doc:record">
      <xsl:copy> 
        <xsl:apply-templates select="doc:field"/>
        <xsl:variable name="url" select="concat('https://www.fakedomain.org/careersection/',
                                                doc:field[@name='JobBoardID'], '/',
                                                '/jobapply.ftl?lang=en&amp;job=',
                                                doc:field[@name='ReqNumber'])" />
        <xsl:element name="field" namespace="http://www.taleo.com/ws/integration/toolkit/2005/07">
            <xsl:attribute name="name">ApplyURL</xsl:attribute>
            <xsl:value-of select="$url"/>
        </xsl:element> 
      </xsl:copy>

   </xsl:template> 

</xsl:transform>

XSLT Demo

答案 1 :(得分:0)

请注意,xsl:elementxsl:attribute指令在要动态定义其QName时很有用。否则,只需使用literal result elements

此样式表

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
               xmlns:doc="http://www.taleo.com/ws/integration/toolkit/2005/07"
               xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07"
               exclude-result-prefixes="doc"> 
   <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template> 

   <xsl:template match="doc:record">
      <xsl:copy> 
        <xsl:apply-templates select="@*|node()"/>
        <field name="ApplyURL">
            <xsl:value-of 
            select="concat(
                'https://www.fakedomain.org/careersection/',
                doc:field[@name='JobBoardID'],
                '/jobapply.ftl?lang=en&amp;job=',
                doc:field[@name='ReqNumber'])" />
        </field>
      </xsl:copy>
   </xsl:template> 
</xsl:stylesheet>

输出:

<ExportXML  xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07" 
            xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
            xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
            xmlns:ns1="http://www.taleo.com/ws/integration/toolkit/2005/07" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <record>
                <field name="Client">Company X</field>
                <field name="TItle">Program Manager</field>
                <field name="ReqNumber">106839</field>
                <field name="JobBoardID">JB-10000</field>
                <field name="PostedDate">2019-04-03</field>
                <field name="City"/>
                <field name="StateProvince"/>
                <field name="Country">United States</field>
                <field name="Category">Professionals</field>
                <field name="JobText">Blah, blah, blah</field>
                <field name="ApplyURL">https://www.fakedomain.org/careersection/JB-10000/jobapply.ftl?lang=en&amp;job=106839</field>
            </record>
            <record>
                <field name="Client">Company X</field>
                <field name="TItle">Director, Sales--Army</field>
                <field name="ReqNumber">106051</field>
                <field name="JobBoardID">JB-13262</field>
                <field name="PostedDate">2019-03-04</field>
                <field name="City"/>
                <field name="StateProvince"/>
                <field name="Country">United States</field>
                <field name="Category">Sales Workers</field>
                <field name="JobText">Blah, blah, blah</field>
                <field name="ApplyURL">https://www.fakedomain.org/careersection/JB-13262/jobapply.ftl?lang=en&amp;job=106051</field>
            </record>
</ExportXML>

这是最好的方法,可以通过将转换更新到XSLT 3.0来确认

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"
               xmlns:doc="http://www.taleo.com/ws/integration/toolkit/2005/07"
               xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07"
               exclude-result-prefixes="doc"
               expand-text="yes">
   <xsl:mode on-no-match="shallow-copy"/>     

   <xsl:template match="doc:record">
      <xsl:copy> 
        <xsl:apply-templates select="@*|node()"/>
        <field name="ApplyURL">https://www.fakedomain.org/careersection/{
                doc:field[@name='JobBoardID']}/jobapply.ftl?lang=en&amp;job={
                doc:field[@name='ReqNumber']}</field>
      </xsl:copy>
   </xsl:template> 
</xsl:stylesheet>