XSLT模板匹配包含xpath的param

时间:2017-04-05 20:04:59

标签: xslt xslt-2.0

我需要对不同的XML响应进行XSL转换,插入处理指令以帮助识别列表元素,以便以后进行XMLtoJSON转换。

示例输入XML:

<?xml version="1.0" encoding="UTF-8"?>
<recipe_collection>
   <last_updated>20170405</last_updated>
   <recipe>
      <name>Split Pea Soup</name>
      <ingredients_list>
         <ingredient>
            <name>Split Peas</name>
            <amount>1 bag</amount>
         </ingredient>
         <ingredient>
            <name>Vegetable Broth</name>
            <amount>32 Ounces</amount>
         </ingredient>
         <ingredient>
            <name>Vegetable Broth</name>
            <amount>32 Ounces</amount>
         </ingredient>
         <ingredient>
            <name>Ham</name>
            <amount>Small</amount>
         </ingredient>
      </ingredients_list>
      <preparation>
         <step>Rinse Peas</step>
         <step>Add ingredients to pressure cooker</step>
         <step>Cook at full pressure for 12 minutes</step>
         <step>Season with salt, pepper, garlic powder to taste</step>
      </preparation>
      <serve_with>
         <name>Bread</name>
      </serve_with>
   </recipe>
</recipe_collection>

示例XSL:

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

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

   <xsl:template match="/recipe_collection/recipe/name[1]|/recipe_collection/recipe/ingredients_list/ingredient[1]|/recipe_collection/recipe/ingredients_list/ingredient[1]|/recipe_collection/recipe/preparation/step[1]|/recipe_collection/recipe/serve_with/name[1]">
      <xsl:processing-instruction name="xml-multiple">
         <xsl:value-of select="local-name()" />
      </xsl:processing-instruction>
      <xsl:copy>
         <xsl:apply-templates select="node()|@*" />
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

然后将原始XML与插入的<?xml-muliple ...?> PI复制:

<?xml version="1.0" encoding="UTF-8"?>
<recipe_collection>
   <last_updated>20170405</last_updated>
   <recipe>
      <?xml-multiple name?>
      <name>Split Pea Soup</name>
      <ingredients_list>
         <?xml-multiple ingredient?>
         <ingredient>
            <name>Split Peas</name>
            <amount>1 bag</amount>
         </ingredient>
         <ingredient>
            <name>Vegetable Broth</name>
            <amount>32 Ounces</amount>
         </ingredient>
         <ingredient>
            <name>Vegetable Broth</name>
            <amount>32 Ounces</amount>
         </ingredient>
         <ingredient>
            <name>Ham</name>
            <amount>Small</amount>
         </ingredient>
      </ingredients_list>
      <preparation>
         <?xml-multiple step?>
         <step>Rinse Peas</step>
         <step>Add ingredients to pressure cooker</step>
         <step>Cook at full pressure for 12 minutes</step>
         <step>Season with salt, pepper, garlic powder to taste</step>
      </preparation>
      <serve_with>
         <?xml-multiple name?>
         <name>Bread</name>
      </serve_with>
   </recipe>
</recipe_collection>

到目前为止一切顺利。现在让这个XSL使用不同的XML模式。我想传入一个包含匹配中使用的路径的参数。

在修改后的样式表中,我定义了参数&#34; xpaths&#34;使用默认路径列表(注意,此参数的值实际上将在运行时传递给XSL):

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

   <xsl:param name="xpaths">/recipe_collection/recipe/name[1]|/recipe_collection/recipe/ingredients_list/ingredient[1]|/recipe_collection/recipe/ingredients_list/ingredient[1]|/recipe_collection/recipe/preparation/step[1]|/recipe_collection/recipe/serve_with/name[1]</xsl:param>

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

   <xsl:template match="$xpaths">
      <xsl:processing-instruction name="xml-multiple">
         <xsl:value-of select="local-name()" />
      </xsl:processing-instruction>
      <xsl:copy>
         <xsl:apply-templates select="node()|@*" />
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

然而,新XSL中的match="$xpaths"无效

其他注意事项:

我使用的XSL解析器允许XSL 2.0。

XSL必须适用于任何模式,包括元素可能没有唯一名称的模式,因此必须使用完整的xpath来指定列表。

最后我为成为XSL新手而道歉。我仍然无法绕过一些转换概念。

感谢您指出正确的方向(或解决方案)。

1 个答案:

答案 0 :(得分:0)

使用像Saxon 9.7 EE或PE这样的XSLT 3.0处理器,您应该能够使用静态变量和阴影属性,例如。

  <xsl:param name="xpaths" static="yes" as="xs:string">/recipe_collection/recipe/name[1]|/recipe_collection/recipe/ingredients_list/ingredient[1]|/recipe_collection/recipe/ingredients_list/ingredient[1]|/recipe_collection/recipe/preparation/step[1]|/recipe_collection/recipe/serve_with/name[1]</xsl:param>

   <xsl:template _match="{$xpaths}">
      <xsl:processing-instruction name="xml-multiple">
         <xsl:value-of select="local-name()" />
      </xsl:processing-instruction>
      <xsl:copy>
         <xsl:apply-templates select="node()|@*" />
      </xsl:copy>
   </xsl:template>

使用纯XSLT 2.0,您需要使用一个样式表,将您的字符串路径作为参数,然后使用插入的匹配属性值输出/生成所需的第二个样式表。