如何在 xslt 中应用引用值的模板?
How do you apply template referencing a value in xslt?
这是我刚刚编造的一个例子(所以不要以错别字或缩进来评判我):-
<?xml version="1.0" encoding="UTF-8"?>
<company id="c123" name="comp 1">
<buildings>
<building id="b1" name="bld1">
<department ref="d1"/>
<department ref="d3"/>
</building>
</buildings>
<departments>
<department id="d1" name="IT">
<desc>Lorem ipsum</desc>
<cto>Mr. X</cto>
</department>
<department id="d2" name="HR">
<desc>Lorem ipsum</desc>
<coo>Mr. Y</coo>
</department>
<department id="d3" name="Finance">
<desc>Lorem ipsum</desc>
<cfo>Mr. Z</cfo>
</department>
</departments>
</company>
所以我想获得类似于每栋建筑的信息,其中包含它所引用的部门的所有详细信息。
我尝试传递参数并在部门模板中使用它,但这没有用。我有一种感觉,我的 与建筑物本身内部的 "department" 相匹配,我的 xpath 做错了,因为我是新手。我的想法是尝试上升到父节点的级别,然后使用 match="../../departments/department[@ref]"
之类的东西,但这也不起作用。
有什么建议吗?
编辑:
预期输出:
<company id="c123" name="comp 1">
<building id="b1" name="bld1">
<department id="d1" name="IT" desc="Lorem ipsum" cto="Mr. X"/>
<department id="d3" name="Finance" desc="Lorem ipsum" cfo="Mr. Z" />
</building>
</company>
我建议对您的问题做出以下回答:
输入:
::::::::::::::
companies.xml
::::::::::::::
<?xml version="1.0" encoding="UTF-8"?>
<company id="c123" name="comp 1">
<buildings>
<building id="b1" name="bld1">
<department ref="d1"/>
<department ref="d3"/>
</building>
</buildings>
<departments>
<department id="d1" name="IT">
<desc>Lorem ipsum</desc>
<cto>Mr. X</cto>
</department>
<department id="d2" name="HR">
<desc>Lorem ipsum</desc>
<coo>Mr. Y</coo>
</department>
<department id="d3" name="Finance">
<desc>Lorem ipsum</desc>
<cfo>Mr. Z</cfo>
</department>
</departments>
</company>
样式表文件:
::::::::::::::
companies.xsl
::::::::::::::
<?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" encoding="utf-8" indent="yes"/>
<!-- Identity template : copy all text nodes, elements and attributes -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- When matching department: do nothing -->
<xsl:template match="departments" />
<xsl:template match="/departments/department" />
<xsl:template match="building">
<!-- create the node building with attributes -->
<building id="{./@id}" name="{./@name}">
<!-- loop on each department and extract the relevant data -->
<xsl:for-each select="./department">
<xsl:variable name="refvar" select="./@ref"/>
<department id="{./@ref}" name="{//department[@id=$refvar]/@name}" desc="{//department[@id=$refvar]/desc}">
<xsl:attribute name="{name(//department[@id=$refvar]/*[position() = 2])}">
<xsl:value-of select="//department[@id=$refvar]/*[position() = 2]"/>
</xsl:attribute>
</department>
</xsl:for-each>
</building>
</xsl:template>
</xsl:stylesheet>
输出:
$ xsltproc companies.xsl companies.xml | xmllint --format -
<?xml version="1.0" encoding="utf-8"?>
<company id="c123" name="comp 1">
<buildings>
<building id="b1" name="bld1">
<department id="d1" name="IT" desc="Lorem ipsum" cto="Mr. X"/>
<department id="d3" name="Finance" desc="Lorem ipsum" cfo="Mr. Z"/>
</building>
</buildings>
</company>
这是我刚刚编造的一个例子(所以不要以错别字或缩进来评判我):-
<?xml version="1.0" encoding="UTF-8"?>
<company id="c123" name="comp 1">
<buildings>
<building id="b1" name="bld1">
<department ref="d1"/>
<department ref="d3"/>
</building>
</buildings>
<departments>
<department id="d1" name="IT">
<desc>Lorem ipsum</desc>
<cto>Mr. X</cto>
</department>
<department id="d2" name="HR">
<desc>Lorem ipsum</desc>
<coo>Mr. Y</coo>
</department>
<department id="d3" name="Finance">
<desc>Lorem ipsum</desc>
<cfo>Mr. Z</cfo>
</department>
</departments>
</company>
所以我想获得类似于每栋建筑的信息,其中包含它所引用的部门的所有详细信息。
我尝试传递参数并在部门模板中使用它,但这没有用。我有一种感觉,我的 与建筑物本身内部的 "department" 相匹配,我的 xpath 做错了,因为我是新手。我的想法是尝试上升到父节点的级别,然后使用 match="../../departments/department[@ref]"
之类的东西,但这也不起作用。
有什么建议吗?
编辑: 预期输出:
<company id="c123" name="comp 1">
<building id="b1" name="bld1">
<department id="d1" name="IT" desc="Lorem ipsum" cto="Mr. X"/>
<department id="d3" name="Finance" desc="Lorem ipsum" cfo="Mr. Z" />
</building>
</company>
我建议对您的问题做出以下回答:
输入:
::::::::::::::
companies.xml
::::::::::::::
<?xml version="1.0" encoding="UTF-8"?>
<company id="c123" name="comp 1">
<buildings>
<building id="b1" name="bld1">
<department ref="d1"/>
<department ref="d3"/>
</building>
</buildings>
<departments>
<department id="d1" name="IT">
<desc>Lorem ipsum</desc>
<cto>Mr. X</cto>
</department>
<department id="d2" name="HR">
<desc>Lorem ipsum</desc>
<coo>Mr. Y</coo>
</department>
<department id="d3" name="Finance">
<desc>Lorem ipsum</desc>
<cfo>Mr. Z</cfo>
</department>
</departments>
</company>
样式表文件:
::::::::::::::
companies.xsl
::::::::::::::
<?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" encoding="utf-8" indent="yes"/>
<!-- Identity template : copy all text nodes, elements and attributes -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- When matching department: do nothing -->
<xsl:template match="departments" />
<xsl:template match="/departments/department" />
<xsl:template match="building">
<!-- create the node building with attributes -->
<building id="{./@id}" name="{./@name}">
<!-- loop on each department and extract the relevant data -->
<xsl:for-each select="./department">
<xsl:variable name="refvar" select="./@ref"/>
<department id="{./@ref}" name="{//department[@id=$refvar]/@name}" desc="{//department[@id=$refvar]/desc}">
<xsl:attribute name="{name(//department[@id=$refvar]/*[position() = 2])}">
<xsl:value-of select="//department[@id=$refvar]/*[position() = 2]"/>
</xsl:attribute>
</department>
</xsl:for-each>
</building>
</xsl:template>
</xsl:stylesheet>
输出:
$ xsltproc companies.xsl companies.xml | xmllint --format -
<?xml version="1.0" encoding="utf-8"?>
<company id="c123" name="comp 1">
<buildings>
<building id="b1" name="bld1">
<department id="d1" name="IT" desc="Lorem ipsum" cto="Mr. X"/>
<department id="d3" name="Finance" desc="Lorem ipsum" cfo="Mr. Z"/>
</building>
</buildings>
</company>