我正在使用XSLT 1.0转换存储在XML中的医疗记录数据。 因为这些是患者记录,虽然可以调整某些文本值,但无法删除任何内容,因此我必须从标识模板开始。
我需要根据逻辑条件调整某些节点的文本内容,例如另一个包含最多 10 个不同 ID 号中的任何一个的同级节点。 我尝试过使用谓词进行过滤,并且由于在XSLT 说明书的第 4 章中提到了它,我尝试应用具有据称更快的"选择"方法的For-Each
,而不是基于Choose-When
逻辑的"筛选"方法。 我发现使用谓词匹配和将 For-Each 的选择与谓词一起使用之间的差异可以忽略不计。 我非常愿意使用密钥,但不太确定如何应用它们来帮助解决我的问题。
我有两个主要问题:
- 对于某些设施,我必须评估同级节点是否包含大量 ID 中的任何一个,例如 10 个。 这使得谓词变得笨拙且可能很慢,如 [Item/number='123' 或 Item/number='789' 或 ... + 10 种或更多其他可能性]。
- 正在处理的某些 XML 文档非常大。 它们最大可达 5MB,我发现一个为 15MB。 在这种最坏的情况下,仅对于我在较大文档中评估的记录类型,必须评估或筛选 9,000 多个节点,并可能进行调整。
至关重要的是,我找到了最有效的方法来匹配和调整满足条件的节点的文本。 我们在处理和记录检索时间方面遇到了严重的延迟。 如果我能找到最佳解决方案,那么我将在多个地方重写旧的 XSLT 模板并真正改进事情。
我有这样的XML:
<Facilities>
<Facility>XYZ</Facility>
<Records>
<!-- lots and lots of other kinds of records here A to Z, long XML before this. -->
<!-- RecordAAA #1 -->
<RecordAAA>
<Item>
<number>123</number>
<definition>123 really means this</definition>
</Item>
<ItemCategory>
<ID>AAA</ID>
<IdDescription>AAA</IdDescription>
</ItemCategory>
</RecordAAA>
<!-- RecordAAA #2 -->
<RecordAAA>
<Item>
<number>456</number>
<definition>456 really means this</definition>
</Item>
<ItemCategory>
<ID>AAA</ID>
<IdDescription>AAA</IdDescription>
</ItemCategory>
</RecordAAA>
<!-- RecordAAA #3 -->
<RecordAAA>
<Item>
<number>123</number>
<definition>123 really means this</definition>
</Item>
<ItemCategory>
<ID>AAA</ID>
<IdDescription>AAA</IdDescription>
</ItemCategory>
</RecordAAA>
<!-- lots and lots of other kinds of records here A to Z, long XML after this. -->
</Records>
</Facilities>
期望输出:根据 RecordAAA #2 的项目/编号文本"456"更改<ItemCategory> <ID>
和<ItemCategory> <IdDescription>
内容, 而 RecordAAA #1 和 #3 只是简单地复制了:
<Facilities>
<Facility>XYZ</Facility>
<Records>
<!-- lots and lots of other kinds of records here A to Z, long XML, before this. -->
<!-- RecordAAA #1 -->
<RecordAAA>
<Item>
<number>123</number>
<definition>123 really means this</definition>
</Item>
<ItemCategory>
<ID>AAA</ID>
<IdDescription>AAA</IdDescription>
</ItemCategory>
</RecordAAA>
<!-- RecordAAA #2 -->
<RecordAAA>
<Item>
<number>456</number>
<definition>456 really means this</definition>
</Item>
<!-- ID and IdDescription have been changed. -->
<ItemCategory>
<ID>BBB</ID>
<IdDescription>BBB</IdDescription>
</ItemCategory>
</RecordAAA>
<!-- RecordAAA #3 -->
<RecordAAA>
<Item>
<number>123</number>
<definition>123 really means this</definition>
</Item>
<ItemCategory>
<ID>AAA</ID>
<IdDescription>AAA</IdDescription>
</ItemCategory>
</RecordAAA>
<!-- lots and lots of other kinds of records here A to Z, long XML, after this. -->
</Records>
</Facilities>
我有这样的 XSLT 模板,当然这有效:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Identity template -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Records/RecordAAA[Item/number='456' or Item/number='789' or Item/number='101112']/ItemCategory">
<ItemCategory>
<ID>BBB</ID>
<IdDescription>BBB</IdDescription>
</ItemCategory>
</xsl:template>
</xsl:stylesheet>
但是,如果我有具有更多代码的设施,并且它开始看起来像这样,我该怎么办:
<xsl:template match="Records/RecordAAA[Item/number='456'
or Item/number='789'
or Item/number='101112'
or Item/number='1314'
or Item/number='1516'
or Item/number='1718'
or Item/number='1920'
or Item/number='2122'
or Item/number='2324'
or Item/number='2526'
or Item/number='2728']/ItemCategory">
<ItemCategory>
<ID>BBB</ID>
<IdDescription>BBB</IdDescription>
</ItemCategory>
</xsl:template>
这仍然会产生所需的输出(就像一长串Choose-When
条件一样),但是我怎样才能更快地完成它?有没有办法真正提高效率?
如果这对您的答案很重要,我们正在使用 Xalan 处理器,而我坚持使用 1.0 版。
非常感谢您的任何扎实见解。
我不确定您是否可以使这些比较运行得更快。
您可以通过在参数或单独的文件中保留工具列表来使代码更简洁。
下面是一个示例 XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name='facilityfile'>fax.xml</xsl:param>
<xsl:variable name='facility' select='document($facilityfile)//facility/@nbr'/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!--
<xsl:template match="Records/RecordAAA[Item/number='456' or Item/number='789' or Item/number='101112']/ItemCategory">
-->
<xsl:template match='ItemCategory'>
<xsl:choose>
<xsl:when test='preceding-sibling::Item/number=$facility'>
<ItemCategory>
<ID>BBB</ID>
<IdDescription>BBB</IdDescription>
</ItemCategory>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
和设施传真.xml内容
<xml>
<facility nbr='456'/>
<facility nbr='567'/>
<facility nbr='678'/>
<facility nbr='789'/>
</xml>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<!-- generate-id(../..) returns the id of the grandparent of number. ie. RecordAAA -->
<xsl:key name="myKey" match="number[.='456' or .='789' or .='101112']" use="generate-id(../..)"/>
<!-- Identity template -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- generate-id(..) returns the parent of ItemCategory. ie. RecordAAA-->
<xsl:template match="ItemCategory[key('myKey', generate-id(..))]">
<ItemCategory>
<ID>BBB</ID>
<IdDescription>BBB</IdDescription>
</ItemCategory>
</xsl:template>
</xsl:stylesheet>