它又是我,但这次我有一个真正的问题...... 我有一个XML,我必须使用另一个XML的过滤器将其转换为另一个XML
File_in.xml:
<?xml version="1.0" encoding="ISO-8859-15"?>
<root>
<item>
<server>001023541</server>
<name>P1</name>
<desc>Production</desc>
<status>1</status>
<ram>1024</ram>
<hdd>8 To</hdd>
</item>
<item>
<server>201012345</server>
<name>P2</name>
<desc>Production</desc>
<status>4</status>
<ram>2048</ram>
<hdd>8 To</hdd>
</item>
<item>
<server>120332416</server>
<name>P1</name>
<desc>Production</desc>
<status>2</status>
<ram>8196</ram>
<hdd>8 To</hdd>
</item>
</root>
另一个XML:
filter.xml
<?xml version="1.0" encoding="ISO-8859-15"?>
<Filtre>
<Bloc5>
<Part1>
<EAN>001023541</EAN>
<EAN>012356549</EAN>
<EAN>012356559</EAN>
<EAN>012356569</EAN>
</Part1>
<Part2>
<EAN>201012345</EAN>
<EAN>201012346</EAN>
<EAN>201012347</EAN>
</Part2>
</Bloc5>
</Filtre>
如果/ root / item / server与/ Filtre / Bloc5 / Part1 / EAN的元素匹配,我替换
<item>
<server>001023541</server>
<name>P1</name>
<desc>Production</desc>
<status>1</status>
<ram>1024</ram>
<hdd>8 To</hdd>
</item>
通过
<item>
<server>MAIN</server>
<status>PRODUCTION</status>
</item>
否则如果/ root / item / server与/ Filtre / Bloc5 / Part2 / EAN的元素匹配,我替换
<item>
<server>201012345</server>
<name>P2</name>
<desc>Production</desc>
<status>4</status>
<ram>2048</ram>
<hdd>8 To</hdd>
</item>
通过
<item>
<server>BACKUP</server>
<status>STOPPED</status>
</item>
,另一个会自动替换为:
<item>
<server>120332416</server>
<name>P1</name>
<desc>Production</desc>
<status>2</status>
<ram>8196</ram>
<hdd>8 To</hdd>
</item>
通过
<item>
<name>OFFLINE</name>
<desc>Production</desc>
</item>
我通过这种方式得到XML的名称(用于过滤):
<!-- filter settings -->
<xsl:param name="filter_xml" />
<xsl:variable name="filter" select="document('$filter_xml')" />
还有我的代码:
<xsl:for-each select="root/item">
<xsl:choose>
<xsl:when test="index-of(($filter/Filtre/Bloc5/Part1/EAN), ./server)">
<item>
<server>MAIN</server>
<status>PRODUCTION</status>
</item>
</xsl:when>
<xsl:when test="index-of(($filter/Filtre/Bloc5/Part2/EAN), ./server)" >
<item>
<server>BACKUP</server>
<status>STOPPED</status>
</item>
</xsl:when >
<xsl:otherwise>
<item>
<name>OFFLINE</name>
<desc>Production</desc>
</item>
</xsl:otherwise>
</xsl:for-each>
但这不起作用......
答案 0 :(得分:2)
更简洁,更有效的解决方案是使用模板匹配而不是曲折的分支。我假设XSLT 2.0是因为您没有使用XSLT版本号标记您的问题,但如果您需要XSLT 1.0,则可以轻松进行调整。
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />
<xsl:variable name="filter" select="document('filter.xml')/*" />
<xsl:template match="/" >
<root>
<xsl:apply-templates select="*/item" />
</root>
</xsl:template>
<xsl:template match="item[server=$filter/Bloc5/Part1/EAN]" >
<item>
<server>MAIN</server>
<status>PRODUCTION</status>
</item>
</xsl:template>
<xsl:template match="item[server=$filter/Bloc5/Part2/EAN]" >
<item>
<server>BACKUP</server>
<status>STOPPED</status>
</item>
</xsl:template>
<xsl:template match="item" >
<item>
<name>OFFLINE</name>
<desc>Production</desc>
</item>
</xsl:template>
</xsl:stylesheet>
感谢您的接受。作为锦上添花,您还可以使用此 ONE 更通用和可扩展的模板替换前两个项目模板。但它是否更简单或更复杂是值得商榷的。
替代通用项目模板(仅适用于XSLT 2.0)...
<xsl:template match="item[server=$filter/Bloc5/*/EAN]" >
<xsl:variable name="part-no"
select="substring-after(local-name(($filter/Bloc5/*[EAN=current()/server])[1]),
'Part') cast as xs:integer" />
<xsl:copy>
<server><xsl:value-of select="('MAIN' ,'BACKUP' )[$part-no]" /></server>
<status><xsl:value-of select="('PRODUCTION','STOPPED')[$part-no]" /></status>
</xsl:copy>
</xsl:template>
答案 1 :(得分:1)
您需要调整两件事:
document()
的路径必须是过滤变量的值。您当前正在传递字符串“$ filter”。你需要改变
<xsl:variable name="filter" select="document('$filter_xml')" />
到<xsl:variable name="filter" select="document($filter_xml)" />
contains()
函数需要每个参数的字符串输入。为了评估针对每个过滤器contains()
的{{1}}测试,请在EAN
元素的谓词过滤器内执行测试。例如,将EAN
更改为<xsl:when test="index-of(($filter/Filtre/Bloc5/Part1/EAN), ./server)">
。如果匹配,则结果将至少为<xsl:when test="$filter/Filtre/Bloc5/Part1/EAN[contains(., ./server)]">
,在测试中评估为EAC
。
应用于示例XSLT:
true()