扫描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> ... ... ... .

我有一个XML文件要通过XSLT转换。它有两种类型的标记,比如X1和X2标记,随机放置在XML文件中。我需要元素E1中X1处理的结果,然后,在该元素E1之后,第二个元素E2具有X2标记的处理结果。 因此,XML文件如下所示:

<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>