Java 将映射传递给XSLT并通过键更改值
我有一个Java 将映射传递给XSLT并通过键更改值,java,xml,xslt,Java,Xml,Xslt,我有一个Map,其中有几个条目,我想使用XSLT应用于XML文档 每当它在XML中找到TESTWORD时,使用下面的键并用映射中的适当值替换它。还要替换该节点的名称 输入: <Company> <Employee> <FirstName>Homer</FirstName> <LastName>Simpson</LastName> <ContactNo>1234567890
Map
,其中有几个条目,我想使用XSLT应用于XML文档
每当它在XML中找到TESTWORD
时,使用下面的键并用映射中的适当值替换它。还要替换该节点的名称
输入:
<Company>
<Employee>
<FirstName>Homer</FirstName>
<LastName>Simpson</LastName>
<ContactNo>1234567890</ContactNo>
<Address>
<City>Springfield</City>
<Note>TESTWORD key1</Note> <!-- change this -->
</Address>
</Employee>
<Employee>
<FirstName>Peter</FirstName>
<LastName>Griffin</LastName>
<ContactNo>0987654321</ContactNo>
<Address>
<City>Quahog</City>
<Note>TESTWORD key2</Note> <!-- change this -->
</Address>
</Employee>
</Company>
<Company>
<Employee>
<FirstName>Homer</FirstName>
<LastName>Simpson</LastName>
<ContactNo>1234567890</ContactNo>
<Address>
<City>Springfield</City>
<NewElem>my value</NewElem> <!-- changed -->
</Address>
</Employee>
<Employee>
<FirstName>Peter</FirstName>
<LastName>Griffin</LastName>
<ContactNo>0987654321</ContactNo>
<Address>
<City>Quahog</City>
<NewElem>another value</NewElem> <!-- changed -->
</Address>
</Employee>
</Company>
Map<String, String> map = new HashMap<>();
map.put("key1", "my value");
map.put("key2", "another value");
try {
TransformerFactory factory = TransformerFactory.newInstance();
Source xslt = new StreamSource(new File("doc.xslt"));
Transformer transformer = factory.newTransformer(xslt);
transformer.setParameter("map", map); // Passing map as parameter
Source text = new StreamSource(new File("doc.xml"));
transformer.transform(text, new StreamResult(new File("newXml.xml")));
} catch (URISyntaxException | TransformerException ex) {}
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes" method="xml" encoding="utf-8" />
<xsl:key name="map" /> <!-- the map with my keys and values -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="Note[.='TESTWORD key1']"> <!-- iterate all params -->
<xsl:element name="NewElem">
<xsl:value-of select="$key1" /> <!-- replace all values -->
</xsl:element>
</xsl:template>
<!--
<xsl:template match="Note[.='TESTWORD key2']">
<xsl:element name="NewElem">
<xsl:value-of select="$key2" />
</xsl:element>
</xsl:template>
-->
</xsl:stylesheet>
荷马
辛普森
1234567890
这里有一种方法可以使用XSLT 1.0和XSLT中的Xalan来实现:
我创建了一个包含静态映射的简单类:
package samples;
import java.util.Map;
public class StaticMap {
private static Map<String, String> map;
public static Map<String, String> getMap() {
return map;
}
public static void setMap(Map<String, String> map) {
StaticMap.map = map;
}
public static String getValue(String key) {
return map.get(key);
}
}
包装样品;
导入java.util.Map;
公共类静态映射{
私有静态地图;
公共静态映射getMap(){
返回图;
}
公共静态无效集合映射(映射映射){
StaticMap.map=map;
}
公共静态字符串getValue(字符串键){
返回map.get(key);
}
}
我没有将映射传递给XSLT,而是将映射加载到我的静态映射类:
Map<String, String> map = new HashMap<>();
map.put("key1", "my value");
map.put("key2", "another value");
try {
TransformerFactory factory = TransformerFactory.newInstance();
Source xslt = new StreamSource(new File("C:\\Users\\Public\\Documents\\doc.xslt"));
Transformer transformer = factory.newTransformer(xslt);
StaticMap.setMap(map);
Source text = new StreamSource(new File("C:\\Users\\Public\\Documents\\doc.xml"));
transformer.transform(text, new StreamResult(new File("C:\\Users\\Public\\Documents\\newXml.xml")));
} catch (Exception ex) {}
Map Map=newhashmap();
map.put(“键1”,“我的值”);
map.put(“键2”,“另一个值”);
试一试{
TransformerFactory=TransformerFactory.newInstance();
Source xslt=new StreamSource(新文件(“C:\\Users\\Public\\Documents\\doc.xslt”);
变压器=工厂新变压器(xslt);
StaticMap.setMap(map);
Source text=new StreamSource(新文件(“C:\\Users\\Public\\Documents\\doc.xml”);
transformer.transform(文本,新的StreamResult(新文件(“C:\\Users\\Public\\Documents\\newXml.xml”));
}捕获(例外情况除外){}
这是我的XSLT。请注意,在XSLT中,节点的模板与文本值为“TESTWORD key1”的元素匹配,我将此更改为只查找以“TESTWORD”开头的值:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:staticMap="xalan://samples.StaticMap"
version="2.0">
<xsl:output indent="yes" method="xml" encoding="utf-8" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="Note[substring(., 1, 8) = 'TESTWORD']"> <!-- iterate all params -->
<xsl:element name="NewElem">
<xsl:value-of select="staticMap:getValue(substring(.,10))" /> <!-- replace all values -->
</xsl:element>
</xsl:template>
</xsl:stylesheet>
这是我的输出:
<?xml version="1.0" encoding="utf-8"?><Company>
<Employee>
<FirstName>Homer</FirstName>
<LastName>Simpson</LastName>
<ContactNo>1234567890</ContactNo>
<Address>
<City>Springfield</City>
<NewElem>my value</NewElem>
<!-- change this -->
</Address>
</Employee>
<Employee>
<FirstName>Peter</FirstName>
<LastName>Griffin</LastName>
<ContactNo>0987654321</ContactNo>
<Address>
<City>Quahog</City>
<NewElem>another value</NewElem>
<!-- change this -->
</Address>
</Employee>
</Company>
荷马
辛普森
1234567890
斯普林菲尔德
我的价值
彼得
格里芬
0987654321
鹌鹑
另一个价值
我的版本(XSLT2.0)在模板内部设置xsl:param
Martin HonnenXSLT 3.0版本:
日志记录:
SLF4J:类路径包含多个SLF4J绑定。
SLF4J:在[jar:file:/ml/fiona/.m2/repository/org/SLF4J/SLF4J-log4j12/1.7.16/SLF4J-log4j12-1.7.16.jar!/org/SLF4J/impl/StaticLoggerBinder.class]中找到绑定
正在将/xslt/employee.xml写入数据库allegro。。。在2020-07-23T15:27:50.805440900
2020-07-23T15:27:51.115639400,一批共完成一份文件
被审核为“超级”的用户已修改/xslt/employee.xml
约翰
史密斯
007007
林肯郡
替换值1
约翰
雌鹿
007009
普特尼
替换值2
简
史密斯
007000
牛津郡
替换值3
简
雌鹿
007001
格拉斯哥
替换值4
声明
的零件没有任何意义。键不是将映射从宿主语言传递到XSLT的工具。传递映射的唯一方法是在XSLT/XPath中有一个等价的构造,即使用Saxon 9.8或更高版本的XSLT 3。但是您将使用中所示的xsl:param
,并且需要将Java映射转换为XdmMap。请注意,您在回答中使用了Xalan:@user1170330,我已更新了我的回答,以包括使用了Xalan。谢谢。具体的好处是什么?我仍然需要单独指定每个匹配项:…
。另外,当使用xsl:variable
而不是xsl:param
时,我无法从Java传递参数。请参阅修订版。(我重构xml内容……对不起,我在思考时有涂鸦的习惯……xsl:variable
和xsl:param
在语法上是相似的。但是技术是完全不同的…@Martin Honnen
(无意冒犯)
:因为尽管map:keys($map)
在我的氧气中工作,但在Java API中却失败了。XSLT 3似乎存在可梳理性问题。因此,XdmMap
的有效性还有待观察…@FionaChen,我建议在Saxon 9.8及更高版本的XSLT 3中使用XdmMap,并使用其s9api
。Java平台本身只有一个XSLT 1处理器,因此它肯定不允许使用XPath 3.1映射,这与您使用的API无关。
<xsl:param name="key1"/>
<xsl:param name="key2"/>
<xsl:param name="key3"/>
<xsl:param name="key4"/>
<xsl:template match="Note[contains(.,'TESTWORD key1')]">
<xsl:element name='{$elemName}'>
<xsl:value-of select="$key1" />
</xsl:element>
</xsl:template>
<xsl:template match="Note[contains(.,'TESTWORD key2')]">
<xsl:element name='{$elemName}'>
<xsl:value-of select="$key2" />
</xsl:element>
</xsl:template>
<xsl:template match="Note[contains(.,'TESTWORD key3')]">
<xsl:element name='{$elemName}'>
<xsl:value-of select="$key3" />
</xsl:element>
</xsl:template>
<xsl:template match="Note[contains(.,'TESTWORD key4')]">
<xsl:element name='{$elemName}'>
<xsl:value-of select="$key4" />
</xsl:element>
</xsl:template>
// create Transformer
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(xsl);
// set parameters
transformer.setParameter("key1", "replaced value1");
transformer.setParameter("key2", "replaced value2");
transformer.setParameter("key3", "replaced value3");
transformer.setParameter("key4", "replaced value4");
<xsl:param name="map" as="map(xs:string, xs:string)"
select="
map {
'key1': 'replaced value1',
'key2': 'replaced value2',
'key3': 'replaced value3',
'key4': 'replaced value4'
}"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:variable name="map-keys" select="map:keys($map)"/>
<xsl:template
match="
Note[some $key in $map-keys
satisfies . = 'TESTWORD ' || $key]">
<xsl:element name='{$elemName}'>
<xsl:value-of select="$map($map-keys[current() = 'TESTWORD ' || .])"/>
</xsl:element>
</xsl:template>
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/ml/fiona/.m2/repository/org/slf4j/slf4j-log4j12/1.7.16/slf4j-log4j12-1.7.16.jar!/org/slf4j/impl/StaticLoggerBinder.class]
writing /xslt/employee.xml to database allegro... on 2020-07-23T15:27:50.805440900
Total One document(s) in One batch is completed on 2020-07-23T15:27:51.115639400
User audited as 'super' has modified /xslt/employee.xml
<?xml version="1.0" encoding="UTF-8"?>
<Company>
<Employee>
<FirstName>John</FirstName>
<LastName>Smith</LastName>
<ContactNo>007007</ContactNo>
<Address>
<City>Lincolnshire</City>
<nameOnChanged>replaced value1</nameOnChanged>
</Address>
</Employee>
<Employee>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<ContactNo>007009</ContactNo>
<Address>
<City>Putney</City>
<nameOnChanged>replaced value2</nameOnChanged>
</Address>
</Employee>
<Employee>
<FirstName>Jane</FirstName>
<LastName>Smith</LastName>
<ContactNo>007000</ContactNo>
<Address>
<City>Oxfordshire</City>
<nameOnChanged>replaced value3</nameOnChanged>
</Address>
</Employee>
<Employee>
<FirstName>Jane</FirstName>
<LastName>Doe</LastName>
<ContactNo>007001</ContactNo>
<Address>
<City>Glasgow</City>
<nameOnChanged>replaced value4</nameOnChanged>
</Address>
</Employee>
</Company>