平台: Saxon 9 - XSLT 2.0
我有3000个xml文档,需要定期编辑,更新和保存。
部分过程涉及在编辑之前从存储库中签出文档,并在编辑完成后定期发布文档。
每个文档都包含一系列单独命名的部分,例如
<part>
<meta>
<place_id>12345</place_id>
<place_name>London</place_name>
<country_id>GB</country_id>
<country_name>United Kingdom</country_name>
</meta>
<text>
<docs>some blurb</docs>
<airport>some blurb LGW LHR</airport>
<trains>some blurb</trains>
<hotels>some blurb</hotels>
<health>some blurb</health>
<attractions>some blurb</attractions>
</text>
</part>
在文本元素中有近100个部分,与所有编辑团队一样,他们偶尔也会定期改变他们对首选订单的看法。也许每年两次。
目前,我们将XML文档部分提供给当前优先顺序的编辑进行编辑和发布。此顺序在动态生成的名为“stdhdg.xml”的外部文档中指定,并显示如下:
<hdgs>
<hdg name="docs" newsort="10"/>
<hdg name="airport" newsort="30"/>
<hdg name="trains" newsort="20"/>
<hdg name="hotels" newsort="40"/>
<hdg name="health" newsort="60"/>
<hdg name="attractions" newsort="50"/>
</hdgs>
首选排序顺序由hdg / @newport指定。
所以我使用这样的模板以正确的顺序处理
<xsl:template match="text">
<xsl:variable name="thetext" select="."/>
<xsl:variable name="stdhead" select="document('stdhdg.xml')"/>
<text>
<xsl:for-each select="$stdhead//hdg">
<xsl:sort data-type="number" order="ascending" select="@newsort"/>
<xsl:variable name="tagname" select="@name"/>
<xsl:variable name="thisnode" select="$thetext/*[local-name() = $tagname]"/>
<xsl:apply-templates select="$thisnode"/>
</xsl:for-each>
</text>
</xsl:template>
但它看起来非常缓慢而且很麻烦,我觉得我应该用钥匙来加速它。
是否有更简单/更简洁的方法来执行此排序操作。
(请不要让我改变编辑的编辑方式。这不仅仅是我一生的价值)
TIA
Feargal
答案 0 :(得分:0)
是的,密钥应该加速这样的查找。这是一个大纲:
<xsl:stylesheet ...>
<xsl:key name="k1" match="text/*" use="local-name()"/>
<xsl:variable name="stdhead" select="document('stdhdg.xml')"/>
...
<xsl:template match="text">
<xsl:variable name="thetext" select="."/>
<text>
<xsl:for-each select="$stdhead//hdg">
<xsl:sort data-type="number" order="ascending" select="@newsort"/>
<xsl:apply-templates select="key('k1', @name, $thetext)"/>
</xsl:for-each>
</text>
</xsl:template>
</xsl:stylesheet>
所有内容都直接在浏览器中输入,因此请将其作为如何处理它的大纲,而不是在经过测试的代码中。
[edit]作为第二个想法,我认为每次处理text
元素时排序都是浪费,所以你可以改为
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:key name="k1" match="text/*" use="local-name()"/>
<xsl:variable name="stdhead" select="document('stdhdg.xml')"/>
<xsl:variable name="sorted-headers" as="element(hdg)*">
<xsl:perform-sort select="$stdhead//hdg">
<xsl:sort select="@newsort" data-type="number"/>
</xsl:perform-sort>
</xsl:variable>
<xsl:template match="text">
<xsl:variable name="thetext" select="."/>
<text>
<xsl:for-each select="$sorted-headers">
<xsl:apply-templates select="key('k1', @name, $thetext)"/>
</xsl:for-each>
</text>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
在文本元素中有 近100个部分,与所有部分一样 编辑团队,他们改变他们的 关注的首选订单 偶尔,但经常,基础。也许 每年两次。
。 。 。 。 。 。
但似乎非常 缓慢而笨重,我觉得我 应该用钥匙来加快速度
每次提交文档进行编辑时对文档进行排序是错误的方法。
最佳解决方案是在更改“stdhdg.xml”文档时对其进行排序并保存每年仅排序2次。
如果'stdhdg.xml'中的更改无法在组织上很好地同步,那么您可以使用重复(比如说每日)作业运行以下转换:
<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:param name="vHeaderLoc" select="'file:///C:/temp/deleteMe/stdhdg.xml'"/>
<xsl:variable name="vHeaderDoc" select=
"document($vHeaderLoc)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"part/@hash
[not(.
=
string(document('file:///C:/temp/deleteMe/stdhdg.xml'))
)
]">
<xsl:attribute name="hash">
<xsl:value-of select="string($vHeaderDoc)"/>
</xsl:attribute>
</xsl:template>
<xsl:template match=
"/*/text[not(/*/@hash
= string(document('file:///C:/temp/deleteMe/stdhdg.xml'))
)
]">
<text>
<xsl:apply-templates select="*">
<xsl:sort data-type="number"
select="$vHeaderDoc/*/hdg[@name=name(current())]"/>
</xsl:apply-templates>
</text>
</xsl:template>
</xsl:stylesheet>
当主要内容XML文档是(注意顶部元素现在具有hash
属性)时:
<part hash="010203040506">
<meta>
<place_id>12345</place_id>
<place_name>London</place_name>
<country_id>GB</country_id>
<country_name>United Kingdom</country_name>
</meta>
<text>
<docs>some blurb</docs>
<airport>some blurb LGW LHR</airport>
<trains>some blurb</trains>
<hotels>some blurb</hotels>
<health>some blurb</health>
<attractions>some blurb</attractions>
</text>
</part>
,stdhdg.xml文件为:
<hdgs>
<hdg name="docs">10</hdg>
<hdg name="airport">30</hdg>
<hdg name="trains">20</hdg>
<hdg name="hotels">40</hdg>
<hdg name="health">60</hdg>
<hdg name="attractions">50</hdg>
</hdgs>
然后上面的转换会生成一个新排序的主内容,其中包含最新的哈希:
<part hash="103020406050">
<meta>
<place_id>12345</place_id>
<place_name>London</place_name>
<country_id>GB</country_id>
<country_name>United Kingdom</country_name>
</meta>
<text>
<docs>some blurb</docs>
<trains>some blurb</trains>
<airport>some blurb LGW LHR</airport>
<hotels>some blurb</hotels>
<attractions>some blurb</attractions>
<health>some blurb</health>
</text>
</part>
请注意:
主内容文档的顶部元素现在具有hash
属性,其值是驻留在stdhdg.xml文档中的排序键的串联。
stdhdg.xml文件的格式也略有改变,因此可以轻松地将键的串联生成为文档的字符串值。
如果主要内容中保存的哈希值与stdhdg.xml中的sort-keys-concatenation相同,则每日运行转换是身份转换。
如果旧散列与stdhdg.xml中的排序键不匹配,则会更新为新散列并重新排序这些节。