Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 组合XSLT中2个列表中的元素_Xml_Xslt - Fatal编程技术网

Xml 组合XSLT中2个列表中的元素

Xml 组合XSLT中2个列表中的元素,xml,xslt,Xml,Xslt,假设我有这样的XML(并且假设我无法更改此XML的格式): 霍布诺布斯 1.49 消化液 89 6克 太多了 3克 5克 我想使用XSLT将其转化为如下内容: <biscuit> <name>Hobnobs</name> <price>1.49</price> <fat>6 grams</fat> <sugar>lots</sugar> <

假设我有这样的XML(并且假设我无法更改此XML的格式):


霍布诺布斯
1.49
消化液
89
6克
太多了
3克
5克
我想使用XSLT将其转化为如下内容:

<biscuit>
     <name>Hobnobs</name>
     <price>1.49</price>
     <fat>6 grams</fat>
     <sugar>lots</sugar>
</biscuit>

霍布诺布斯
1.49
6克
太多了
我如何在XSLT中执行类似的操作?我可以循环浏览第一个饼干列表(名称和价格)并从第二个列表(营养价值)中提取元素吗

我对XSL不太了解,所以欢迎提供任何建议

干杯


JD.

第二部分可以使用XPath。在第一个列表上执行循环,一旦找到名称,就使用XPath查询第二个列表中所需的内容。

您可以在第二部分使用XPath。在第一个列表上执行循环,一旦获得名称,就使用XPath查询第二个列表中所需的内容。

此XSLT:

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

<xsl:key name="bisquit-info" match="/root/biscuitInfo" use="@name"/>

<xsl:template match="root">
    <xsl:copy>
        <xsl:apply-templates select="biscuit/name"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="name">
    <bisquit>
        <xsl:copy-of select="."/>
        <xsl:copy-of select="following-sibling::price[1]"/>
        <xsl:copy-of select="key('bisquit-info', .)/nutritionalValue/*"/>
    </bisquit>
</xsl:template> 
</xsl:stylesheet>

使用这样的XML输入(只是为了良好的格式添加了根节点)


霍布诺布斯
1.49
消化液
89
6克
太多了
3克
5克
将提供以下结果:

<root>
<bisquit>
    <name>Hobnobs</name>
    <price>1.49</price>
    <fat>6 grams</fat>
    <sugar>lots</sugar>
</bisquit>
<bisquit>
    <name>Digestives</name>
    <price>89.00</price>
    <fat>3 grams</fat>
    <sugar>5 grams</sugar>
</bisquit>
</root>

霍布诺布斯
1.49
6克
太多了
消化液
89
3克
5克
设计并不理想,但这会起作用。我使用键,假设输入树可以很大。

此XSLT:

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

<xsl:key name="bisquit-info" match="/root/biscuitInfo" use="@name"/>

<xsl:template match="root">
    <xsl:copy>
        <xsl:apply-templates select="biscuit/name"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="name">
    <bisquit>
        <xsl:copy-of select="."/>
        <xsl:copy-of select="following-sibling::price[1]"/>
        <xsl:copy-of select="key('bisquit-info', .)/nutritionalValue/*"/>
    </bisquit>
</xsl:template> 
</xsl:stylesheet>

使用这样的XML输入(只是为了良好的格式添加了根节点)


霍布诺布斯
1.49
消化液
89
6克
太多了
3克
5克
将提供以下结果:

<root>
<bisquit>
    <name>Hobnobs</name>
    <price>1.49</price>
    <fat>6 grams</fat>
    <sugar>lots</sugar>
</bisquit>
<bisquit>
    <name>Digestives</name>
    <price>89.00</price>
    <fat>3 grams</fat>
    <sugar>5 grams</sugar>
</bisquit>
</root>

霍布诺布斯
1.49
6克
太多了
消化液
89
3克
5克

设计并不理想,但这会起作用。我使用键,假设输入树可以很大。

两个示例。此样式表使用clasic完全递归:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kNutChildByBisName" match="nutritionalValue/*"
             use="../../@name"/>
    <xsl:key name="kElemByPrecedingName" match="biscuit/*[not(self::name)]"
             use="preceding-sibling::name[1]"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="name" mode="group">
        <bisquit>
            <xsl:apply-templates select=".|key('kNutChildByBisName',.)|
                                         key('kElemByPrecedingName',.)"/>
        </bisquit>
    </xsl:template>
    <xsl:template match="biscuit">
        <xsl:apply-templates mode="group"/>
    </xsl:template>
    <xsl:template match="biscuitInfo"/>
    <xsl:template match="node()" mode="group"/>
</xsl:stylesheet>

此样式表使用细粒度遍历:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:key name="kNutByBisName" match="nutritionalValue"
                 use="../@name"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="biscuitInfo"/>
    <xsl:template match="biscuit">
        <xsl:apply-templates select="node()[1]|following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="name[1]" name="group">
        <bisquit>
            <xsl:call-template name="identity"/>
            <xsl:apply-templates select="key('kNutByBisName',.)/node()[1]"/>
        </bisquit>
        <xsl:apply-templates select="following-sibling::name[1]" mode="group"/>
    </xsl:template>
    <xsl:template match="name"/>
    <xsl:template match="name" mode="group">
        <xsl:call-template name="group"/>
    </xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="biscuit/name">
  <biscuit>
    <xsl:call-template name="identity"/>
    <xsl:apply-templates select=
    "following-sibling::price[1]
    |
      ../../biscuitInfo[@name = current()]/*"/>
  </biscuit>
 </xsl:template>

 <xsl:template match="biscuit">
  <xsl:apply-templates select="name"/>
 </xsl:template>

 <xsl:template match="nutritionalValue">
   <xsl:apply-templates/>
 </xsl:template>
 <xsl:template match="biscuitInfo"/>
</xsl:stylesheet>

通过此输入:

<root>
    <biscuit>
        <name>Hobnobs</name>
        <price>1.49</price>
        <name>Digestives</name>
        <price>89.00</price>
    </biscuit>
    <biscuitInfo name="Hobnobs">
        <nutritionalValue>
            <fat>6 grams</fat>
            <sugar>lots</sugar>
        </nutritionalValue>
    </biscuitInfo>
    <biscuitInfo name="Digestives">
        <nutritionalValue>
            <fat>3 grams</fat>
            <sugar>5 grams</sugar>
        </nutritionalValue>
    </biscuitInfo>
</root>

霍布诺布斯
1.49
消化液
89
6克
太多了
3克
5克
两种输出:

<root>
    <bisquit>
        <name>Hobnobs</name>
        <price>1.49</price>
        <fat>6 grams</fat>
        <sugar>lots</sugar>
    </bisquit>
    <bisquit>
        <name>Digestives</name>
        <price>89.00</price>
        <fat>3 grams</fat>
        <sugar>5 grams</sugar>
    </bisquit>
</root>

霍布诺布斯
1.49
6克
太多了
消化液
89
3克
5克
注意:您正在执行两项任务:分组和交叉引用


编辑:在组中只有
名称
的情况下进行更好的细粒度遍历。

两个示例。此样式表使用clasic完全递归:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kNutChildByBisName" match="nutritionalValue/*"
             use="../../@name"/>
    <xsl:key name="kElemByPrecedingName" match="biscuit/*[not(self::name)]"
             use="preceding-sibling::name[1]"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="name" mode="group">
        <bisquit>
            <xsl:apply-templates select=".|key('kNutChildByBisName',.)|
                                         key('kElemByPrecedingName',.)"/>
        </bisquit>
    </xsl:template>
    <xsl:template match="biscuit">
        <xsl:apply-templates mode="group"/>
    </xsl:template>
    <xsl:template match="biscuitInfo"/>
    <xsl:template match="node()" mode="group"/>
</xsl:stylesheet>

此样式表使用细粒度遍历:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:key name="kNutByBisName" match="nutritionalValue"
                 use="../@name"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="biscuitInfo"/>
    <xsl:template match="biscuit">
        <xsl:apply-templates select="node()[1]|following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="name[1]" name="group">
        <bisquit>
            <xsl:call-template name="identity"/>
            <xsl:apply-templates select="key('kNutByBisName',.)/node()[1]"/>
        </bisquit>
        <xsl:apply-templates select="following-sibling::name[1]" mode="group"/>
    </xsl:template>
    <xsl:template match="name"/>
    <xsl:template match="name" mode="group">
        <xsl:call-template name="group"/>
    </xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="biscuit/name">
  <biscuit>
    <xsl:call-template name="identity"/>
    <xsl:apply-templates select=
    "following-sibling::price[1]
    |
      ../../biscuitInfo[@name = current()]/*"/>
  </biscuit>
 </xsl:template>

 <xsl:template match="biscuit">
  <xsl:apply-templates select="name"/>
 </xsl:template>

 <xsl:template match="nutritionalValue">
   <xsl:apply-templates/>
 </xsl:template>
 <xsl:template match="biscuitInfo"/>
</xsl:stylesheet>

通过此输入:

<root>
    <biscuit>
        <name>Hobnobs</name>
        <price>1.49</price>
        <name>Digestives</name>
        <price>89.00</price>
    </biscuit>
    <biscuitInfo name="Hobnobs">
        <nutritionalValue>
            <fat>6 grams</fat>
            <sugar>lots</sugar>
        </nutritionalValue>
    </biscuitInfo>
    <biscuitInfo name="Digestives">
        <nutritionalValue>
            <fat>3 grams</fat>
            <sugar>5 grams</sugar>
        </nutritionalValue>
    </biscuitInfo>
</root>

霍布诺布斯
1.49
消化液
89
6克
太多了
3克
5克
两种输出:

<root>
    <bisquit>
        <name>Hobnobs</name>
        <price>1.49</price>
        <fat>6 grams</fat>
        <sugar>lots</sugar>
    </bisquit>
    <bisquit>
        <name>Digestives</name>
        <price>89.00</price>
        <fat>3 grams</fat>
        <sugar>5 grams</sugar>
    </bisquit>
</root>

霍布诺布斯
1.49
6克
太多了
消化液
89
3克
5克
注意:您正在执行两项任务:分组和交叉引用


编辑:在组中只有
名称
的情况下,进行更好的细粒度遍历。

传统的标识规则被几个模板覆盖。无键,无精细纹理遍历:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:key name="kNutByBisName" match="nutritionalValue"
                 use="../@name"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="biscuitInfo"/>
    <xsl:template match="biscuit">
        <xsl:apply-templates select="node()[1]|following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="name[1]" name="group">
        <bisquit>
            <xsl:call-template name="identity"/>
            <xsl:apply-templates select="key('kNutByBisName',.)/node()[1]"/>
        </bisquit>
        <xsl:apply-templates select="following-sibling::name[1]" mode="group"/>
    </xsl:template>
    <xsl:template match="name"/>
    <xsl:template match="name" mode="group">
        <xsl:call-template name="group"/>
    </xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="biscuit/name">
  <biscuit>
    <xsl:call-template name="identity"/>
    <xsl:apply-templates select=
    "following-sibling::price[1]
    |
      ../../biscuitInfo[@name = current()]/*"/>
  </biscuit>
 </xsl:template>

 <xsl:template match="biscuit">
  <xsl:apply-templates select="name"/>
 </xsl:template>

 <xsl:template match="nutritionalValue">
   <xsl:apply-templates/>
 </xsl:template>
 <xsl:template match="biscuitInfo"/>
</xsl:stylesheet>

应用于此源XML时(基本上是提供的,但包装在单个顶部元素中):


霍布诺布斯
1.49
消化液
89
6克
太多了
3克
5克
生成所需的正确结果

<product>
   <biscuit>
      <name>Hobnobs</name>
      <price>1.49</price>
      <fat>6 grams</fat>
      <sugar>lots</sugar>
   </biscuit>
   <biscuit>
      <name>Digestives</name>
      <price>89.00</price>
      <fat>3 grams</fat>
      <sugar>5 grams</sugar>
   </biscuit>
</product>

霍布诺布斯
1.49
6克
太多了
消化液
89
3克
5克
注意事项

<product>
   <biscuit>
      <name>Hobnobs</name>
      <price>1.49</price>
      <fat>6 grams</fat>
      <sugar>lots</sugar>
   </biscuit>
   <biscuit>
      <name>Digestives</name>
      <price>89.00</price>
      <fat>3 grams</fat>
      <sugar>5 grams</sugar>
   </biscuit>
</product>
  • 使用和覆盖标识规则是一种基本的XSLT设计模式,它的使用方便了几乎所有转换的编写

  • 使用
    而不是
    允许并行执行
    ,这在不久的将来可能变得越来越重要

  • 键可以用作优化,但对于小型XML文档(如提供的文档),这不是必需的,而且键的使用与解决此问题的中心思想无关


  • 传统标识规则被几个模板覆盖。无键,无精细纹理遍历:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:strip-space elements="*"/>
        <xsl:key name="kNutByBisName" match="nutritionalValue"
                     use="../@name"/>
        <xsl:template match="node()|@*" name="identity">
            <xsl:copy>
                <xsl:apply-templates select="node()[1]|@*"/>
            </xsl:copy>
            <xsl:apply-templates select="following-sibling::node()[1]"/>
        </xsl:template>
        <xsl:template match="biscuitInfo"/>
        <xsl:template match="biscuit">
            <xsl:apply-templates select="node()[1]|following-sibling::node()[1]"/>
        </xsl:template>
        <xsl:template match="name[1]" name="group">
            <bisquit>
                <xsl:call-template name="identity"/>
                <xsl:apply-templates select="key('kNutByBisName',.)/node()[1]"/>
            </bisquit>
            <xsl:apply-templates select="following-sibling::name[1]" mode="group"/>
        </xsl:template>
        <xsl:template match="name"/>
        <xsl:template match="name" mode="group">
            <xsl:call-template name="group"/>
        </xsl:template>
    </xsl:stylesheet>
    
    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:template match="node()|@*" name="identity">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="biscuit/name">
      <biscuit>
        <xsl:call-template name="identity"/>
        <xsl:apply-templates select=
        "following-sibling::price[1]
        |
          ../../biscuitInfo[@name = current()]/*"/>
      </biscuit>
     </xsl:template>
    
     <xsl:template match="biscuit">
      <xsl:apply-templates select="name"/>
     </xsl:template>
    
     <xsl:template match="nutritionalValue">
       <xsl:apply-templates/>
     </xsl:template>
     <xsl:template match="biscuitInfo"/>
    </xsl:stylesheet>
    
    
    
    应用于此源XML时(基本上是提供的,但包装在单个顶部元素中):

    
    霍布诺布斯
    1.49
    消化液
    89