扫描xml文件一次或两次?
我有一个XML文件要通过XSLT转换。它有两种类型的标记,比如X1和X2标记,随机放置在XML文件中。我需要元素E1中X1处理的结果,然后,在该元素E1之后,第二个元素E2具有X2标记的处理结果。 因此,XML文件如下所示:扫描xml文件一次或两次?,xml,xslt,Xml,Xslt,我有一个XML文件要通过XSLT转换。它有两种类型的标记,比如X1和X2标记,随机放置在XML文件中。我需要元素E1中X1处理的结果,然后,在该元素E1之后,第二个元素E2具有X2标记的处理结果。 因此,XML文件如下所示: <root> ... <X1/> ... <X2/> ... <X1/> ... <X1/> ... <X2/> ... etc. </root> ... ... ... .
<root>
...
<X1/>
...
<X2/>
...
<X1/>
...
<X1/>
...
<X2/>
...
etc.
</root>
...
...
...
...
...
...
等
以及结果文件:
<root1>
<E1>
<x1/>
<x1/>
<x1/>
</E1>
<E2>
<x2/>
<x2/>
</E2>
</root1>
问题:我可以一次完成所有这些吗,还是需要循环两次输入文件?
(现实更加复杂,但这是根本问题) 此样式表将为您提供所需的结果,例如您发布的示例,以及作为输入的数据
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" />
<xsl:variable name="x1" select="//X1"/>
<xsl:variable name="x2" select="//X2"/>
<xsl:template match="root">
<root1>
<E1>
<xsl:apply-templates select="$x1"/>
</E1>
<E2>
<xsl:apply-templates select="$x2"/>
</E2>
</root1>
</xsl:template>
<xsl:template match="X1">
<x1><xsl:apply-templates/></x1>
</xsl:template>
<xsl:template match="X2">
<x2><xsl:apply-templates/></x2>
</xsl:template>
</xsl:stylesheet>
或者,在XSLT 2.0中:
<xsl:template match="X2|X1">
<xsl:element name="{lower-case(name())}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
实际上,由于根节点
模板准确地选择了您感兴趣的节点,因此您不必在每个模板中重复此操作,并且可以使用*
:
<xsl:template match="*">
<xsl:element name="{lower-case(name())}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
您的意思是要将所有X1
包装在E1
中,将所有X2
包装在E2
中吗?如果这是您想要的,它可以一次完成。您还想要小写的元素名称吗?它们是空的还是包含更多数据、元素、文本的节点?这只是表示Xn元素已被处理。嗯。。。。在我看来,首先处理所有X1元素,然后处理所有X2元素,所以扫描两次。也许它必须扫描一个元素,确定它是X1还是X2,然后应用适当的X1或X2模板。一个d然后转到下一个元素。但结果不会进入相应的元素E1或E2……它会读取节点两次,但会从内存中读取。它不会扫描文件两次。它将文件加载到DOM树中,然后使用XPath选择节点并将其存储在变量中,然后遍历匹配节点的DOM树处理模板。如果树跨越多个输入XML文件,XSLT 2是否也会通过包含这些XML文件列表的索引文件读取整棵树?@Erik,XSLT1.0和2.0都使用一个处理和数据模型,其中每个输入文档首先被完全解析为一个树,然后该树作为任何转换的输入。正在开发的XSLT 3.0试图定义流,以避免非常大的文档占用内存,同时允许使用XSLT/XPath。我认为这可能对您的情况有所帮助,但我不知道是否有任何XSLT 3.0处理器已经实现了这一点。
translate(name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')
<xsl:template match="*">
<xsl:element name="{lower-case(name())}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>