为什么我会看到另一个位置(xslt)的值?

时间:2019-12-13 13:35:32

标签: xml xslt xslt-1.0

很抱歉这个菜鸟问题,我已经通过添加不是很优雅的空模板解决了这个问题,但是谁能帮助我理解为什么我在输出中仍然看到另一个“级别”的值?

这是我的xml的样子:

<root>
 <offers>
  <theme>
    <type>theme1</type>
    <name>...</name>
    <slug>...</slug>
    <description>...</description>
    <total>32</total>
    <url_title>...</url_title>
    <url_anchor>...</url_anchor>
    <url>...</url>
    <offers>
      <row>
        <offer>
          <name>travel</type>
          <id>68232</id>
   </theme>
   <theme>
    <type>theme2</type>
    <name>...</name>
    <slug>...</slug>
    <description>...</description>
    <total>32</total>
    <url_title>...</url_title>
    <url_anchor>...</url_anchor>
    <url>...</url>
    <offers>
      <row>
        <offer>
          <name>clowns</type>
          <id>222</id>
   </theme>
 </offers>
</root>

每个主题仅包含1个报价。我想同时显示主题/要约/行/要约的报价,所以我使用了:

<xsl:template match="root/offers">
    <xsl:apply-templates select="theme[position() mod 2 = 1]" mode="row" />
</xsl:template>

<xsl:template match="theme" mode="row">
    <xsl:apply-templates select="offers/row/offer/." mode="offer1" />
    <xsl:apply-templates select="following-sibling::theme[1]" mode="offer2" />
</xls:template>

<xsl:template match="*" mode="offer1">
=== This one showed the offer correctly 
</template>

<xsl:template match="offer" mode="offer2">
=== This one kept showing the 'type', 'name' 'slug' 
=== values from the theme node, 
=== even though I didn't ask for them
</xsl:template>

我只是通过添加空模板来修复它,就像这样:

<xsl:template match="theme/type" mode="offer2"/>
<xsl:template match="theme/name" mode="offer2"/>
<xsl:template match="theme/slug" mode="offer2"/>

我只想了解我哪里出错了。我一直对同级语法不满意(那里不能使用'.'...),我需要在'theme'级别使用mod 2 = 1,因为每个主题仅包含一个提议。

2 个答案:

答案 0 :(得分:1)

出现问题的原因是Built-in Template Rules

让我们看看这个规则:

<xsl:template match="theme" mode="row">
    <xsl:apply-templates select="offers/row/offer/." mode="offer1" />
    <xsl:apply-templates select="following-sibling::theme[1]" mode="offer2" />
</xls:template>

请注意如何应用选择offer孙子和主题兄弟的模板。因此,由于在theme模式下没有针对offer2元素的规则,因此将应用内置规则:元素将应用子节点,输出文本节点。

这就是为什么转换(不是您说的规则)输出

的原因
  

主题节点中的“类型”,“名称”,“子弹”,值,即使我   没有要他们

更新:来自OP的评论

  

是的,那么我如何将它们丢失,同时仍将它们配对

推送样式:将规则更改为

<xsl:template match="theme" mode="row">
    <xsl:apply-templates 
         select="offers/row/offer" mode="offer1" />
    <xsl:apply-templates 
         select="following-sibling::theme[1]/offers/row/offer" mode="offer2" />
</xls:template>

拉样式:添加此规则可覆盖'offer2'模式下的文本节点内置规则。

<xsl:template match="text()" mode="offer2"/>

答案 1 :(得分:0)

您已在此处https://www.w3.org/TR/1999/REC-xslt-19991116将其标记为XSLT 1.0版规范

如果您想使用https://www.w3.org/TR/2009/PER-xslt20-20090421/上的2.0版本

列表可以在https://www.w3.org/TR/xslt/all/

中找到

您的答案就在于副本在1.0中的工作方式:https://www.w3.org/TR/1999/REC-xslt-19991116#copying,但也许对这里的2.0规范有更好的解释https://www.w3.org/TR/xslt20/#copying

您拥有的此版本1.0可能会有所不同,这可能会影响答案的有效性。

好的,我们已经解决了这个问题,让我们使用您发布的XML。现在,我添加了另一个报价(现实生活中可能会发生吗?),所以我展示了如何通过id获取所有报价和订单。

在大多数情况下,我会尝试简化选择器,在此说明如何进行选择,看来您想对报价进行排序,所以在此示例中。

<?xml version="1.0"?>
<xsl:stylesheet  version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:html="http://www.w3.org/1999/xhtml"
 exclude-result-prefixes="xsl html">

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*"/>

<xsl:template match="root/offers">
  <!-- made this root up -->
  <myoffers>
    <!-- since we do not need anything from the theme -->
    <xsl:apply-templates select="theme/offers/row/offer">
      <!-- or sort by <xsl:sort select="name" data-type="string"/> -->
        <xsl:sort select="id" data-type="number"/>
     </xsl:apply-templates>
  </myoffers>
</xsl:template>


  <xsl:template match="row/offer">       
  <!-- could create new node name here like myoffers -->
  <xsl:copy>
   <!-- order the elements -->
   <xsl:apply-templates select="id" />
   <xsl:apply-templates select="name" />
  </xsl:copy>
</xsl:template>

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

<!-- strip/normalize space, not sure you need but to show how -->
<xsl:template match="text()">
    <xsl:value-of select="normalize-space()"/>
</xsl:template>

</xsl:stylesheet>

示例输出:

<myoffers>
  <offer>
    <id>222</id>
    <name>clowns</name>
  </offer>
  <offer>
    <id>723</id>
    <name>burnt meat</name>
  </offer>
  <offer>
    <id>68232</id>
    <name>travel</name>
  </offer>
</myoffers>

我使用的示例输入XML:

<root>
   <offers>
  <theme>
    <type>theme1</type>
    <name>...</name>
    <slug>...</slug>
    <description>...</description>
    <total>32</total>
    <url_title>.uuseful..</url_title>
    <url_anchor>fun</url_anchor>
    <url>...</url>
    <offers>
      <row>
        <offer>
          <name>travel</name>
          <id>68232</id>
             </offer>
      </row>
     </offers>
   </theme>
   <theme>
    <type>theme2</type>
    <name>.namer..</name>
    <slug>.slugger..</slug>
    <description>.I am me.</description>
    <total>32</total>
    <url_title>...</url_title>
    <url_anchor>...</url_anchor>
    <url>...</url>
    <offers>
      <row>
        <offer>
          <name>clowns   </name>
          <id>  222</id>
        </offer>
      </row>
     </offers>
   </theme>
        <theme>
    <type>theme2</type>
    <name>.namer..</name>
    <slug>.slugger..</slug>
    <description>.I am me.</description>
    <total>32</total>
    <url_title>...</url_title>
    <url_anchor>...</url_anchor>
    <url>...</url>
    <offers>
      <row>
        <offer>
          <name>burnt meat</name>
          <id>  723</id>
        </offer>
      </row>
     </offers>
   </theme>
  </offers>
</root>

如果将其粘贴到http://fiddle.frameless.io/

,则可以测试所有内容