加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

将节点插入另一个XML,创建新元素(或更新现有元素)并重新排序生成

发布时间:2020-12-16 00:00:35 所属栏目:百科 来源:网络整理
导读:好吧,即使我正在努力使用该网站,也要发布我的第一个问题.过去两天我一直试图找到解决方案而没有成功.使用本网站上的一些类似问题的答案( this,this,this,this和许多其他人),我已经取得了一些进展,但完整的(和正确的!)解决方案仍然逃脱了我. 我有一个现有的X
好吧,即使我正在努力使用该网站,也要发布我的第一个问题.过去两天我一直试图找到解决方案而没有成功.使用本网站上的一些类似问题的答案( this,this,this,this和许多其他人),我已经取得了一些进展,但完整的(和正确的!)解决方案仍然逃脱了我.

我有一个现有的XML(file1.xml),我必须根据我正在生成的另一个XML(file2.xml)进行更新:file2的内容必须包含在file1中,遵守我稍后将说明的一些规则(内容文件已过度简化,仅显示相关元素):

file1.xml

<?xml version="1.0" encoding="UTF-8"?>
<list>
    <decade lastyear="2012" firstyear="2011">
        <year value="2012">
            <issue year="2012"  number="242" />
            <issue year="2012"  number="241" />
            <issue year="2012"  number="240" />
        </year>
        <year value="2011">
            <issue year="2011"  number="238" />
            <issue year="2011"  number="237" />
            <issue year="2011"  number="236" />
            <issue year="2011"  number="235" />
        </year>
    </decade>
    <decade lastyear="2010" firstyear="2001">
        <year value="2010">
            <issue year="2010"  number="234" />
            <issue year="2010"  number="233" />
            <issue year="2010"  number="232" />
            <issue year="2010"  number="231" />
            <issue year="2010"  number="230" />
        </year>
        <year value="2009">
            <issue year="2009"  number="229" />
            <issue year="2009"  number="228" />
            <issue year="2009"  number="227" />
            <issue year="2009"  number="226" />
            <issue year="2009"  number="225" />
        </year>
           ...
    </decade>
 </list>

file2.xml

<?xml version="1.0" encoding="UTF-8"?>
<issue year="2013" number="245" />
...

如前所述,必须在file1上插入file2的内容,并遵守一些规则:

>如果file1上不存在问题’年份(即,如果插入年份的第一期),则必须创建(已经完成)
>必须在相应年份插入新问题(已完成)
>十年必须更新,以反映最后插入的一年(有这个问题!)
>问题元素必须按年份和编号按降序排序
>如果问题的一年属于新的十年,那么必须创建这个问题以及相应的子年和问题.
>在结果文档中,所有元素必须按降序排序:十年(去年),年(值)和问题(年份和数字)

我正在使用Saxon-HE 9.4.0.6和我迄今为止完成的xsl就是这个:

XSL

<?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"
    version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="no" encoding="UTF-8"/>

    <xsl:variable name="up" select="document('../test/ExcelStory/file2.xml')"/>
    <xsl:variable name="year" select="$up/issue/@year" />

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

    <xsl:template match="decade" >
        <xsl:copy>
            <xsl:apply-templates select="* | @*"/>
            <xsl:choose>
                <xsl:when test="year[1]/@value lt $year">
                    <year value="{$year}"/>
                </xsl:when>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="year[@value=$year]">
        <xsl:copy>
            <xsl:apply-templates select="* | @*"/>
            <xsl:apply-templates select="$up/*" />
        </xsl:copy>
    </xsl:template>    
</xsl:stylesheet>

此样式表假定file1.xml上的内容在读取时已经被排序(就是这种情况).

我想知道我是否必须使用’模式’进行多次传递,首先根据年份创建十年(如果需要),然后在正确的十年(第二次传递??)中插入年份,之后插入关于正确年份(第三次传递??)的问题,最后重新排序所有元素(甚至是另一个传递??)或者是否可以更有效地进行所有必需的处理(一次或两次传递). Michael Key先生建议在其他地方使用xsl:for-each进行这种处理,但在这种情况下我不知道它是否适合更好(更容易?).

即使这个问题看起来与stackoverflow上的其他问题类似,我认为还有一些额外的复杂性使得它值得一读(并且可能会回答,我希望!).

如果您能提供一些有关如何进行的建议或者您是否可以向我指出其他资源,我将不胜感激.

我要做的不是尝试添加新问题,而是将两个文件中的所有问题结合起来然后重新创建结构.

这可能不适用于您的实际用例,因为您说:

(content of files has been oversimplified to show only relevant
elements)

但希望它能给你另一个视角和/或起点.

您可能希望添加标识转换并将xsl:copy-of和xsl:perform-sort替换为xsl:apply-templates.您还需要更新xsl:param以指向外部文件.

XML输入(略微修改以增加更多年份并更改编号以进行测试)

<list>
    <decade lastyear="2012" firstyear="2011">
        <year value="2012">
            <issue year="2012"  number="242" />
            <issue year="2012"  number="241" />
            <issue year="2012"  number="240" />
        </year>
        <year value="2011">
            <issue year="2011"  number="238" />
            <issue year="2011"  number="237" />
            <issue year="2011"  number="236" />
            <issue year="2011"  number="235" />
        </year>
    </decade>
    <decade lastyear="2010" firstyear="2001">
        <year value="2010">
            <issue year="2010"  number="234" />
            <issue year="2010"  number="232" />
            <issue year="2010"  number="233" />
            <issue year="2010"  number="231" />
            <issue year="2010"  number="230" />
        </year>
        <year value="2009">
            <issue year="2009"  number="229" />
            <issue year="2009"  number="228" />
            <issue year="2009"  number="227" />
            <issue year="2009"  number="226" />
            <issue year="2009"  number="225" />
        </year>
        <year value="2001">
            <issue year="2001"  number="123" />
        </year>
    </decade>
</list>

XSLT 2.0

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <!--This can be changed to point to an external XML file.-->
    <xsl:param name="up">
        <issue year="2013" number="245" />
        <issue year="2002" number="135" />
        <issue year="2011" number="239" />
    </xsl:param>

    <xsl:template match="/*">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:for-each-group select="($up/issue|*/*/issue)" group-by="floor((number(@year) - 1) div 10)">
                <xsl:sort select="@year" data-type="number" order="descending"/>
                <decade lastyear="{max(current-group()/@year)}" firstyear="{min(current-group()/@year)}">
                    <xsl:for-each-group select="current-group()" group-by="@year">
                        <xsl:sort select="current-grouping-key()" data-type="number" order="descending"/>                   
                        <year value="{current-grouping-key()}">
                            <xsl:perform-sort select="current-group()">
                                <xsl:sort select="@number" data-type="number" order="descending"/>
                            </xsl:perform-sort>
                        </year>
                    </xsl:for-each-group>
                </decade>
            </xsl:for-each-group>           
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

XML输出

<list>
   <decade lastyear="2013" firstyear="2011">
      <year value="2013">
         <issue year="2013" number="245"/>
      </year>
      <year value="2012">
         <issue year="2012" number="242"/>
         <issue year="2012" number="241"/>
         <issue year="2012" number="240"/>
      </year>
      <year value="2011">
         <issue year="2011" number="239"/>
         <issue year="2011" number="238"/>
         <issue year="2011" number="237"/>
         <issue year="2011" number="236"/>
         <issue year="2011" number="235"/>
      </year>
   </decade>
   <decade lastyear="2010" firstyear="2001">
      <year value="2010">
         <issue year="2010" number="234"/>
         <issue year="2010" number="233"/>
         <issue year="2010" number="232"/>
         <issue year="2010" number="231"/>
         <issue year="2010" number="230"/>
      </year>
      <year value="2009">
         <issue year="2009" number="229"/>
         <issue year="2009" number="228"/>
         <issue year="2009" number="227"/>
         <issue year="2009" number="226"/>
         <issue year="2009" number="225"/>
      </year>
      <year value="2002">
         <issue year="2002" number="135"/>
      </year>
      <year value="2001">
         <issue year="2001" number="123"/>
      </year>
   </decade>
</list>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读