XLST 2.0 – 基于先前数据添加额外元素

huangapple go评论70阅读模式
英文:

XLST 2.0 - add extra element based on previous data

问题

我可以基于先前的数据添加一个元素吗?我想将其添加到现有的复杂XSLT规则集中。这就是为什么我不想从另一个程序开始的原因。

问题的简化版本:



1235



1235



1236


我想根据现有id的时间添加一个额外的元素。



1235

first


1235

second


1236

second

任何id都将使用一次或两次。对于相似的id,较旧的始终在较新的之前。id字段始终位于<time>字段之前。

如何添加<sequence>元素?我可以使用Java扩展,但那样我会在另一个元素内操作。通过Saxon库,我可以使用XSLT 2.0。

附加:问题的更详细版本如下XML:




1




1






2




更新:回顾过去,非常感谢大家提供的出色答案!

英文:

Can I add an element based on previous data? I would like to add that to an existing complex XSLT ruleset. That's why I wouldn't like to start with another program.

A simplified version of the problem:

&lt;featurecollection&gt;
  &lt;feature&gt; 
    &lt;id&gt;1235&lt;/id&gt;    &lt;!-- same id --&gt; 
    &lt;time&gt;100&lt;/time&gt; &lt;!-- older ----&gt; 
  &lt;/feature&gt;
  &lt;feature&gt;
    &lt;id&gt;1235&lt;/id&gt;    &lt;!-- same id --&gt; 
    &lt;time&gt;101&lt;/time&gt; &lt;!-- newer ----&gt; 
  &lt;/feature&gt;
  
  &lt;feature&gt;
    &lt;id&gt;1236&lt;/id&gt;    &lt;!-- unique id -&gt; 
    &lt;time&gt;102&lt;/time&gt; &lt;!-- is new ----&gt; 
  &lt;/feature&gt;
&lt;/featurecollection&gt;

I would like to add an extra element based upon the time of an existing id.

&lt;featurecollection&gt;
  &lt;feature&gt; 
    &lt;id&gt;1235&lt;/id&gt;           &lt;!-- same id --&gt; 
    &lt;time&gt;100&lt;/time&gt;        &lt;!-- older ----&gt; 
    &lt;sequence&gt;first&lt;/time&gt;
  &lt;/feature&gt;
  &lt;feature&gt;
    &lt;id&gt;1235&lt;/id&gt;           &lt;!-- same id --&gt; 
    &lt;time&gt;101&lt;/time&gt;        &lt;!-- newer ----&gt; 
    &lt;sequence&gt;second&lt;/time&gt;
  &lt;/feature&gt;
  
  &lt;feature&gt;
    &lt;id&gt;1236&lt;/id&gt;            &lt;!-- unique id -&gt; 
    &lt;time&gt;102&lt;/time&gt;         &lt;!-- is new ----&gt; 
    &lt;sequence&gt;second&lt;/time&gt;
  &lt;/feature&gt;
&lt;/featurecollection&gt;

Any id will be used either once or twice. With similar id's the oldest is always before the newest. The id field is always before the &lt;time&gt; field.

How can I add that &lt;sequence&gt; element? I could use a Java extension, but then I am operating within another element. Via the Saxon lib I can work with XSLT 2.0.

ADDED: A more elaborate version of the problem is the following XML:

&lt;featurecollection&gt;
  &lt;feature&gt;
    &lt;object&gt;
      &lt;identification&gt;
        &lt;id&gt;1&lt;/id&gt;
      &lt;/identification&gt;
      &lt;time&gt;20230804120304&lt;/time&gt;
      &lt;!-- insert here: &lt;sequence&gt;first&lt;/sequence&gt; --&gt;
    &lt;/object&gt;
    &lt;object&gt;
      &lt;identification&gt;
        &lt;id&gt;1&lt;/id&gt;
      &lt;/identification&gt;
      &lt;time&gt;20230804120305&lt;/time&gt;
      &lt;!-- insert here: &lt;sequence&gt;second&lt;/sequence&gt; --&gt;
    &lt;/object&gt;
  &lt;/feature&gt;
  &lt;feature&gt;
    &lt;object&gt;
      &lt;identification&gt;
        &lt;id&gt;2&lt;/id&gt;
      &lt;/identification&gt;
      &lt;time&gt;20230804120304&lt;/time&gt;
      &lt;!-- insert here: &lt;sequence&gt;second&lt;/sequence&gt; --&gt;
    &lt;/object&gt;
  &lt;/feature&gt;
&lt;/featurecollection&gt;

UPDATE: looking back, thank you all very much for the great answers!

答案1

得分: 1

以下是翻译好的部分:

"对于添加额外元素的条件对我来说不太清楚,因此我提出了一个工作假设,即当当前“feature”的“id”元素的值与前面的“feature”元素的“id”元素的值不同的时候,才会添加额外元素。

这可能完全不符合您的要求,因此您需要根据您的要求来调整条件。

以下是根据我之前提出的工作假设添加新元素的示例。我假设您在使用XSLT2,但也可能是XSLT3甚至XSLT1,差异不会太大。

一个示例样式表,根据我之前描述的工作假设,可以是以下内容:

<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0"
  exclude-result-prefixes="#all">

  <xsl:output indent="yes" />

  <xsl:template match="/">
    <xsl:apply-templates />
  </xsl:template>
  
  <xsl:template match="attribute()|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*,node()" />
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="feature">
    <xsl:copy>
        <xsl:apply-templates select="@*,node()" />
        <xsl:if test="not(. is //feature[1]) 
                      and
                      not(id = ./preceding-sibling::feature/id)">
          <sequence>second</sequence>
        </xsl:if>
    </xsl:copy>    
  </xsl:template>
  
</xsl:stylesheet>

我使用的输入是您的输入的一个版本,已编辑为格式良好。

<featurecollection>
  <feature> 
    <id>1235</id>    <!-- 相同的id --> 
    <time>100</time> <!-- 旧的 --> 
  </feature>
  
  <feature>
    <id>1235</id>    <!-- 相同的id --> 
    <time>101</time> <!-- 新的 --> 
  </feature>
  
  <feature>
    <id>1236</id>    <!-- 独特的id --> 
    <time>102</time> <!-- 是新的 --> 
  </feature>
</featurecollection>

输出如下:

<?xml version="1.0" encoding="UTF-8"?>
<featurecollection>
   <feature>
      <id>1235</id>    <!-- 相同的id --> 
      <time>100</time> <!-- 旧的 --> 
   </feature>
   <feature>
      <id>1235</id>    <!-- 相同的id --> 
      <time>101</time> <!-- 新的 --> 
    </feature>
    <feature>
      <id>1236</id>    <!-- 独特的id --> 
      <time>102</time> <!-- 是新的 --> 
      <sequence>second</sequence>
   </feature>
</featurecollection>
英文:

It's not clear to me what the condition is for adding the additional element, so I've made a working hypothesis that it is when the value of the id element of the current feature is different from the values of the id element of the previous feature elements.

That may not at all be your requirement so you'll have to adapt the condition to your requirement.

Below is an example of how to add a new element based upon that hypothesis. I'm assuming XSLT2 but it could well be XSLT3 or even XSLT1 and would not change that much.

Am example stylesheet that adds an additional sequence element based upon the working hypothesis that I describe previously could be the following:

&lt;xsl:stylesheet 
  xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;
  version=&quot;2.0&quot;
  exclude-result-prefixes=&quot;#all&quot;&gt;

  &lt;xsl:output indent=&quot;yes&quot; /&gt;

  &lt;xsl:template match=&quot;/&quot; &gt;
    &lt;xsl:apply-templates /&gt;
  &lt;/xsl:template&gt;
  
  &lt;xsl:template match=&quot;attribute()|node()&quot; &gt;
    &lt;xsl:copy&gt;
        &lt;xsl:apply-templates select=&quot;@*,node()&quot; /&gt;
    &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;
  
  &lt;xsl:template match=&quot;feature&quot; &gt;
    &lt;xsl:copy&gt;
        &lt;xsl:apply-templates select=&quot;@*,node()&quot; /&gt;
        &lt;xsl:if test=&quot;not(. is //feature[1]) 
                      and
                      not(id = ./preceding-sibling::feature/id)&quot; &gt;
          &lt;sequence&gt;second&lt;/sequence&gt;
        &lt;/xsl:if&gt;
    &lt;/xsl:copy&gt;    
  &lt;/xsl:template&gt;
  
&lt;/xsl:stylesheet&gt;

The input I've used is a version of your input, edited for well-formedness.

&lt;featurecollection&gt;
  &lt;feature&gt; 
    &lt;id&gt;1235&lt;/id&gt;    &lt;!-- same id --&gt; 
    &lt;time&gt;100&lt;/time&gt; &lt;!-- older --&gt; 
  &lt;/feature&gt;
  
  &lt;feature&gt;
    &lt;id&gt;1235&lt;/id&gt;    &lt;!-- same id --&gt; 
    &lt;time&gt;101&lt;/time&gt; &lt;!-- newer --&gt; 
  &lt;/feature&gt;
  
  &lt;feature&gt;
    &lt;id&gt;1236&lt;/id&gt;    &lt;!-- unique id --&gt; 
    &lt;time&gt;102&lt;/time&gt; &lt;!-- is new --&gt; 
  &lt;/feature&gt;
&lt;/featurecollection&gt;

with output:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;featurecollection&gt;
   &lt;feature&gt;
      &lt;id&gt;1235&lt;/id&gt;    &lt;!-- same id --&gt; 
      &lt;time&gt;100&lt;/time&gt; &lt;!-- older --&gt; 
   &lt;/feature&gt;
   &lt;feature&gt;
      &lt;id&gt;1235&lt;/id&gt;    &lt;!-- same id --&gt; 
      &lt;time&gt;101&lt;/time&gt; &lt;!-- newer --&gt; 
    &lt;/feature&gt;
    &lt;feature&gt;
      &lt;id&gt;1236&lt;/id&gt;    &lt;!-- unique id --&gt; 
      &lt;time&gt;102&lt;/time&gt; &lt;!-- is new --&gt; 
      &lt;sequence&gt;second&lt;/sequence&gt;
   &lt;/feature&gt;
&lt;/featurecollection&gt;

答案2

得分: 1

如果每个feature包含一个或两个具有相同idobject,那么你可以简单地使用以下方式:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" 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>

<xsl:template match="object">
	<xsl:copy>
		<xsl:apply-templates/>
		<sequence>
			<xsl:value-of select="if(position()=last()) then 'second' else 'first'" />
		</sequence>
	</xsl:copy>
</xsl:template>

</xsl:stylesheet>
英文:

(referring to your "more elaborate version" of the input)

If each feature contains either one or two objects (with identical ids) then you could do simply:

XSLT 2.0

&lt;xsl:stylesheet version=&quot;2.0&quot; 
xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
&lt;xsl:output method=&quot;xml&quot; version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; indent=&quot;yes&quot;/&gt;
&lt;xsl:strip-space elements=&quot;*&quot;/&gt;

&lt;!-- identity transform --&gt;
&lt;xsl:template match=&quot;@*|node()&quot;&gt;
	&lt;xsl:copy&gt;
		&lt;xsl:apply-templates select=&quot;@*|node()&quot;/&gt;
	&lt;/xsl:copy&gt;
&lt;/xsl:template&gt;

&lt;xsl:template match=&quot;object&quot;&gt;
	&lt;xsl:copy&gt;
		&lt;xsl:apply-templates/&gt;
		&lt;sequence&gt;
			&lt;xsl:value-of select=&quot;if(position()=last()) then &#39;second&#39; else &#39;first&#39;&quot; /&gt;
		&lt;/sequence&gt;
	&lt;/xsl:copy&gt;
&lt;/xsl:template&gt;

&lt;/xsl:stylesheet&gt;

huangapple
  • 本文由 发表于 2023年8月4日 02:19:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76830695.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定