Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将映射传递给XSLT并通过键更改值_Java_Xml_Xslt - Fatal编程技术网

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>