我正在尝试在输入XML是任意的情况下进行XSLT转换。唯一不变的是它将有一个以"first"开头的节点。我需要得到该节点的值,它是直接的同级节点。但是,以下模板只生成XML声明。
如果重要的话,这段代码是使用Nokogiri XML解析器的Ruby代码。然而,我认为这更多的是一个XSLT/XPath问题,而不是Ruby问题,因此需要相应地进行标记。
输入XML:
<?xml version="1.0"?>
<employees>
<employee>
<first_name>Winnie</first_name>
<last_name>the Pooh</last_name>
</employee>
<employee>
<first_name>Jamie</first_name>
<last_name>the Weeh</last_name>
</employee>
</employees>
所需输出XML:
<?xml version="1.0"?>
<people>
<person>
<first>Winnie</first>
<last>the Pooh</last>
</person>
<person>
<first>Jamie</first>
<last>the Weeh</last>
</person>
</people>
XSLT:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="/">
<xsl:for-each select="node()[starts-with(name(), 'first')]">
<people>
<person>
<name>
<first><xsl:value-of select="." /></first>
<last><xsl:value-of select="following-sibling::*[1]" /></last>
</name>
</person>
</people>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
如果输入XML像您建议的那样任意,我看不出如何将employee/employee更改为persons/person。然而,使用可以获得大致正确的效果
<xsl:template match="*">
<xsl:copy><xsl:apply-templates/></xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(name(), 'first')]">
<first><xsl:apply-templates/></first>
</xsl:template>
<xsl:template match="*[preceding-sibling::*[1][starts-with(name(), 'first')]]">
<last><xsl:apply-templates/></last>
</xsl:template>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<!-- match the node that has a name starting with 'first' -->
<xsl:template match="node()[starts-with(name(), 'first')]">
<xsl:element name="people">
<xsl:element name="person">
<xsl:element name="name">
<xsl:element name="first">
<xsl:value-of select="." />
</xsl:element>
<xsl:element name="last">
<xsl:value-of select="following-sibling::*[1]" />
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:element>
<xsl:apply-templates />
</xsl:template>
<!-- stop the processor walking the rest of the tree and hitting text nodes -->
<xsl:template match="text()|@*" />
</xsl:stylesheet>
使用.//node()
而不是node()
。