Xml 我可以优化这个XSL转换吗?它可以将包含未知列的记录转换为网格格式?
我想优化下面的XSL转换。我已经包含了样本输入数据,样本输出是创建的。输入数据来自一个数据库,每行有一个记录元素,选定的每列有子元素。可以有任意数量、任意顺序和任意名称的列。我事先不知道这些(除了Id元素)。我需要将该数据转换为网格XML格式,定义所使用的列,然后为每个记录包含行元素,每个列包含单元格元素。输入数据包括一个Columns元素,其子元素定义了需要在输出中显示的列。我不知道哪一个专栏会提前发表。列下的所有元素都需要显示在输出中。输出中列/单元格的顺序由列子元素中的顺序属性确定。与列的名称匹配的记录子元素为输出中相应的单元格元素提供数据Record忽略没有匹配列的子元素。并非所有列子元素都将具有相应的记录子元素;对于它们,我们需要输出一个空的单元格元素 我可以让这个XSL工作得更好吗?我知道每个人都是“坏的”。我能再给这个做模板吗?谢谢 XML输入:Xml 我可以优化这个XSL转换吗?它可以将包含未知列的记录转换为网格格式?,xml,optimization,xslt,Xml,Optimization,Xslt,我想优化下面的XSL转换。我已经包含了样本输入数据,样本输出是创建的。输入数据来自一个数据库,每行有一个记录元素,选定的每列有子元素。可以有任意数量、任意顺序和任意名称的列。我事先不知道这些(除了Id元素)。我需要将该数据转换为网格XML格式,定义所使用的列,然后为每个记录包含行元素,每个列包含单元格元素。输入数据包括一个Columns元素,其子元素定义了需要在输出中显示的列。我不知道哪一个专栏会提前发表。列下的所有元素都需要显示在输出中。输出中列/单元格的顺序由列子元素中的顺序属性确定。与列的
<?xml version="1.0" encoding="utf-8" ?>
<!-- The root element could have any name -->
<Data>
<!-- There could be any number of Record elements -->
<Record>
<!-- Elements here may have any name and be in any order and may not be included in Columns -->
<!-- For a particular XML file, all Record elements have the same child elements in the same order -->
<Id>234542</Id>
<Name>Tom Winter</Name>
<SSN>XXX-XX-3317</SSN>
<Facility>East Coast Hospital</Facility>
<Status>AC</Status>
</Record>
<Record>
<Id>345223</Id>
<Name>John Doe</Name>
<SSN>XXX-XX-2344</SSN>
<Facility>St. Joseph West</Facility>
<Status>DE</Status>
</Record>
<Columns>
<!-- There may be any number of element here and they can be in any order -->
<Name label="Patient Name" display="yes" order="2"/>
<MRN label="MRN #" display="yes" order="1"/>
<BirthDate label="Birth Date" align="right" display="yes" order="3"/>
<SSN label="SSN" display="yes" order="9" notSortable="yes"/>
<DischargeDate label="Discharge Date" align="right" display="no" order="7"/>
<Address label="Address" display="yes" order="8"/>
<Facility label="Facility" display="yes" order="4"/>
</Columns>
</Data>
234542
汤姆·温特
XXX-XX-3317
东海岸医院
自动控制
345223
无名氏
XXX-XX-2344
圣约瑟夫西部酒店
判定元件
XSL:
XML输出:
<grid name="exampleGrid">
<column label="MRN #" name="MRN" align="" />
<column label="Patient Name" name="Name" align="" />
<column label="Birth Date" name="BirthDate" align="right" />
<column label="Facility" name="Facility" align="" />
<column label="Discharge Date" name="DischargeDate" align="right" />
<column label="Address" name="Address" align="" />
<column label="SSN" name="SSN" align="" />
<row key="234542">
<cell align=""></cell>
<cell align="">Tom Winter</cell>
<cell align="right"></cell>
<cell align="">East Coast Hospital</cell>
<cell align="right"></cell>
<cell align=""></cell>
<cell align="">XXX-XX-3317</cell>
</row>
<row key="345223">
<cell align=""></cell>
<cell align="">John Doe</cell>
<cell align="right"></cell>
<cell align="">St. Joseph West</cell>
<cell align="right"></cell>
<cell align=""></cell>
<cell align="">XXX-XX-2344</cell>
</row>
</grid>
汤姆·温特
东海岸医院
XXX-XX-3317
无名氏
圣约瑟夫西部酒店
XXX-XX-2344
我将这样做:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="vColumns" select="/*/Columns/*"/>
<xsl:template match="/*">
<grid name="exampleGrid">
<xsl:apply-templates select="$vColumns">
<xsl:sort select="@order" data-type="number"/>
</xsl:apply-templates>
<xsl:apply-templates select="Record"/>
</grid>
</xsl:template>
<xsl:template match="Columns/*">
<column label="{@label}" name="{local-name()}" align="{@align}"/>
</xsl:template>
<xsl:template match="Record">
<xsl:variable name="vCurrent" select="."/>
<row key="{Id}">
<xsl:for-each select="$vColumns">
<xsl:sort select="@order" data-type="number"/>
<cell align="{@align}">
<xsl:value-of
select="$vCurrent/*[local-name()
= local-name(current())]"/>
</cell>
</xsl:for-each>
</row>
</xsl:template>
</xsl:stylesheet>
注意:序列
$vColumns
中的节点保留了它们的标识,现在我们可以使用模式匹配来进行匹配。我将这样做:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="vColumns" select="/*/Columns/*"/>
<xsl:template match="/*">
<grid name="exampleGrid">
<xsl:apply-templates select="$vColumns">
<xsl:sort select="@order" data-type="number"/>
</xsl:apply-templates>
<xsl:apply-templates select="Record"/>
</grid>
</xsl:template>
<xsl:template match="Columns/*">
<column label="{@label}" name="{local-name()}" align="{@align}"/>
</xsl:template>
<xsl:template match="Record">
<xsl:variable name="vCurrent" select="."/>
<row key="{Id}">
<xsl:for-each select="$vColumns">
<xsl:sort select="@order" data-type="number"/>
<cell align="{@align}">
<xsl:value-of
select="$vCurrent/*[local-name()
= local-name(current())]"/>
</cell>
</xsl:for-each>
</row>
</xsl:template>
</xsl:stylesheet>
注意:序列
$vColumns
中的节点保留了它们的标识,现在我们可以使用模式匹配来匹配它们。对于XSLT 1.0处理器,您可以使用扩展函数,如exsl:node set
?在这种情况下,我建议只对//Columns/*
进行一次排序,将结果存储在结果树片段中,用扩展函数将其转换为节点集,所有这些都在全局变量中完成,然后将变量与已排序的节点一起使用,而不是一次又一次地排序。@Martin Honnen:+1好建议。听起来不错。您知道这种类型的节点集函数在MSXML中是否可用吗?对于XSLT 1.0处理器,是否可以使用扩展函数,如exsl:node set
?在这种情况下,我建议只对//Columns/*
进行一次排序,将结果存储在结果树片段中,用扩展函数将其转换为节点集,所有这些都在全局变量中完成,然后将变量与已排序的节点一起使用,而不是一次又一次地排序。@Martin Honnen:+1好建议。听起来不错。您知道这种类型的节点集函数在MSXML中是否可用吗?非常好。不知道为什么我没有把实际的记录节点放在变量中而不是id中。现在看起来很明显@汤姆·温特:不客气@Flack:您可能还对我上一次更新中的XSLT2.0解决方案感兴趣。这是一个后续问题,因为我对XSL行话不太了解。在XSLT1.0示例中,您将$vRTFColumns和$vColumns的内容称为什么?我假设$vColumns包含一个节点集。可能已经回答了我自己的问题:是否有地方可以找到节点集和结果树片段之间差异的示例@汤姆·温特:是的,而且$VRTF列持有一张非常好的支票。不知道为什么我没有把实际的记录节点放在变量中而不是id中。现在看起来很明显@汤姆·温特:不客气@Flack:您可能还对我上一次更新中的XSLT2.0解决方案感兴趣。这是一个后续问题,因为我对XSL行话不太了解。在XSLT1.0示例中,您将$vRTFColumns和$vColumns的内容称为什么?我假设$vColumns包含一个节点集。可能已经回答了我自己的问题:是否有地方可以找到节点集和结果树片段之间差异的示例@汤姆·温特:是的,而且$VRTF列持有
<grid name="exampleGrid">
<column label="MRN #" name="MRN" align="" />
<column label="Patient Name" name="Name" align="" />
<column label="Birth Date" name="BirthDate" align="right" />
<column label="Facility" name="Facility" align="" />
<column label="Discharge Date" name="DischargeDate" align="right" />
<column label="Address" name="Address" align="" />
<column label="SSN" name="SSN" align="" />
<row key="234542">
<cell align=""></cell>
<cell align="">Tom Winter</cell>
<cell align="right"></cell>
<cell align="">East Coast Hospital</cell>
<cell align="right"></cell>
<cell align=""></cell>
<cell align="">XXX-XX-3317</cell>
</row>
<row key="345223">
<cell align=""></cell>
<cell align="">John Doe</cell>
<cell align="right"></cell>
<cell align="">St. Joseph West</cell>
<cell align="right"></cell>
<cell align=""></cell>
<cell align="">XXX-XX-2344</cell>
</row>
</grid>
<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:variable name="vRTFColumns">
<xsl:for-each select="/*/Columns/*">
<xsl:sort select="@order" data-type="number"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="vColumns"
select="msxsl:node-set($vRTFColumns)/*"/>
<xsl:template match="/*">
<grid name="exampleGrid">
<xsl:for-each select="$vColumns">
<column label="{@label}"
name="{local-name()}"
align="{@align}"/>
</xsl:for-each>
<xsl:apply-templates select="Record"/>
</grid>
</xsl:template>
<xsl:template match="Record">
<xsl:variable name="vCurrent" select="."/>
<row key="{Id}">
<xsl:for-each select="$vColumns">
<cell align="{@align}">
<xsl:value-of
select="$vCurrent/*[local-name()
= local-name(current())]"/>
</cell>
</xsl:for-each>
</row>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="vColumns" as="element()*">
<xsl:perform-sort select="/*/Columns/*">
<xsl:sort select="@order" data-type="number"/>
</xsl:perform-sort>
</xsl:variable>
<xsl:template match="/*">
<grid name="exampleGrid">
<xsl:apply-templates select="$vColumns"/>
<xsl:apply-templates select="Record"/>
</grid>
</xsl:template>
<xsl:template match="Columns/*">
<column label="{@label}" name="{local-name()}" align="{@align}"/>
</xsl:template>
<xsl:template match="Record">
<xsl:variable name="vCurrent" select="."/>
<row key="{Id}">
<xsl:for-each select="$vColumns">
<cell align="{@align}">
<xsl:value-of
select="$vCurrent/*[local-name()
= local-name(current())]"/>
</cell>
</xsl:for-each>
</row>
</xsl:template>
</xsl:stylesheet>