我正在尝试使用XSLT更新我拥有的XML文档。它需要对文档进行多项更改以将其转换为其他一些规范。
我想做的是多次更新同一节点。另一种查看方式是,我想在文档上进行多次传递,并且每次传递都可以更新同一节点。
我所有的谷歌搜索提示都使用xsl:template的'mode'属性,但是所有'mode'属性的示例都涉及两次输出节点-就像在目录中使用标题并使用它的情况一样再次作为章节标题。我不想输出两次节点,我想更新两次。
我的样本XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version = '2.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<!-- identity transform (copy over the document) -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- wrap all BBB nodes in parenthesis -->
<xsl:template match="BBB" >
<xsl:copy>
(<xsl:apply-templates select="@*|node()" />)
</xsl:copy>
</xsl:template>
<!-- any BBB that has a CCC should get an attribute indicating so -->
<xsl:template match="BBB[CCC]">
<xsl:copy>
<xsl:attribute name="hasC">true</xsl:attribute>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我的示例xml文档:
<?xml version="1.0" encoding="UTF-8"?>
<source>
<AAA>
<BBB>Bee bee bee</BBB>
<BBB>Bee two bee two bee two</BBB>
</AAA>
<AAA>
<BBB/>
<CCC>
<DDD/>
</CCC>
<BBB>
<CCC/>
</BBB>
</AAA>
</source>
当前输出:
<?xml version="1.0" encoding="UTF-8"?><source>
<AAA>
<BBB>
(Bee bee bee)
</BBB>
<BBB>
(Bee two bee two bee two)
</BBB>
</AAA>
<AAA>
<BBB>
()
</BBB>
<CCC>
<DDD/>
</CCC>
<BBB hasC="true">
<CCC/>
</BBB>
</AAA>
</source>
如您所见,具有“ CCC”的BBB节点仅使用第二个模板进行了一次更新-第一个模板未对其进行修改。理想情况下,我希望输出为
<BBB hasC="true">
(<CCC/>)
</BBB>
这可能吗?我知道我可以通过将两个模板组合在一起来实现此目的,但是我真的想将它们分开以保持可读性和可维护性-两个模板来自不同的要求,并且将它们分开是理想的。
我想我可以有两个XSLT文件,并通过两次调用XSLT处理器将它们链接在一起,但是我希望我不需要这样做。
编辑:基于很多评论,我认为我误解了有关XSLT和转换的一些基本知识。
我的问题是:我有一堆符合规范的XML文档。另一个人对此规范进行了更新,因此我需要创建一个批处理/可编写脚本的过程,以便能够更新大量这些XML文档,以便它们与该新规范匹配。
其中一些新更新如下所示。
1)<string lang="FR">hello</string>
需要更改为<string lang="fra">hello</string>
2)<a><b><string>Color</string><b></a>
需要更改为<a><b><string>Colour</string></b></a>
,但请勿触摸<a><c><string>Color</string></c></a>
3)所有<orgName><string>***anytext***</string></orgName>
需要更改为<orgName><string>My Company: ***anytext***</string></orgName>
4)所有<orgName><string></string></orgName>
节点都需要更改为<organisationName><string></string></orgisationName>
等等。有很多特定的更新可以多次应用于相同的节点,并且这些更新足够多,因此对文件进行多次传递似乎是一个更好的主意,然后创建一个包罗万象的模板,将所有这些更新合并为一个大模板。
我应该使用XSLT尝试执行此操作吗?我是否需要将这些更改分解为多个文件并将它们链接到脚本中?我可以在单个.xslt文件中进行所有这些更新吗?
就像您更新的示例输入的示例一样:XSLT之后
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" doctype-public="XSLT-compat"
encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<!-- identity transform (copy over the document) -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- wrap all BBB nodes in parenthesis -->
<xsl:template match="BBB">
<xsl:copy>
<xsl:if test="CCC">
<xsl:attribute name="hasC">true</xsl:attribute>
</xsl:if>
(<xsl:apply-templates select="@*|node()" />)
</xsl:copy>
</xsl:template>
<xsl:template match="orgName[string]">
<organisationName>
<xsl:apply-templates />
</organisationName>
</xsl:template>
<xsl:template match="a/b/string[text()='Color']">
<xsl:text>Colour</xsl:text>
</xsl:template>
<xsl:template match="orgName/string/text()">
<xsl:text>Company:</xsl:text>
<xsl:value-of select="." />
</xsl:template>
<xsl:template match="string[@lang='FR']">
<xsl:copy>
<xsl:attribute name="lang">fra</xsl:attribute>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当应用于示例输入XML时
<?xml version="1.0" encoding="UTF-8"?>
<source>
<AAA>
<BBB>Bee bee bee</BBB>
<BBB>Bee two bee two bee two</BBB>
<test>
<string lang="FR">hello</string>
</test>
<a>
<b>
<string>Color</string>
</b>
</a>
<a>
<c>
<string>Color</string>
</c>
</a>
<orgName>
<string>***anytext***</string>
</orgName>
<orgName>
<notstring>***anytext***</notstring>
</orgName>
</AAA>
<AAA>
<BBB />
<CCC>
<DDD />
</CCC>
<BBB>
<CCC />
</BBB>
</AAA>
</source>
产生以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<source>
<AAA>
<BBB>(Bee bee bee)</BBB>
<BBB>(Bee two bee two bee two)</BBB>
<test>
<string lang="fra">hello</string>
</test>
<a>
<b>Colour</b>
</a>
<a>
<c>
<string>Color</string>
</c>
</a>
<organisationName>
<string>Company:***anytext***</string>
</organisationName>
<orgName>
<notstring>***anytext***</notstring>
</orgName>
</AAA>
<AAA>
<BBB>()</BBB>
<CCC>
<DDD />
</CCC>
<BBB hasC="true">
(<CCC />)
</BBB>
</AAA>
</source>
您已经提到,更新中添加的4个要求仅是应应用于输入XML的许多更改列表的示例,因此这仅是如何处理同一节点上的各种更改的示例-例如:
<xsl:template match="orgName[string]">
匹配orgName
包含一个节点的节点string
。经过
<organisationName>
<xsl:apply-templates />
</organisationName>
此模板重命名orgName
为organisationName
。
第二模板相匹配的text()
一个的string
在一个节点orgName
的节点:
<xsl:template match="orgName/string/text()">
并Company:
在此文本前面添加:
<xsl:text>Company:</xsl:text>
<xsl:value-of select="." />
两个模板的结果:
<organisationName>
<string>Company:***anytext***</string>
</organisationName>
来自示例输入的orgName
<orgName><notstring>***anytext***</notstring></orgName>
以及文本保持不变(orgName
不包含)string
。
我还删除了与模板匹配BBB[CCC]
的设置hasC
属性。相反,我添加了
<xsl:if test="CCC">
<xsl:attribute name="hasC">true</xsl:attribute>
</xsl:if>
到模板匹配BBB
。
我不建议使用XSLT来应用所有必需的更改,因为我不知道必须应用所有特定的更改-它实际上取决于所需更改的输入和完整规范。我只是想提供一个示例,说明如何使用单个XSLT处理您在问题中提到的更改。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句