【问题标题】:Iteratively insert values from params从 params 迭代地插入值
【发布时间】:2020-07-20 11:50:16
【问题描述】:

我有一个大约 10 个参数(键值对)的列表,我想将它们应用于 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 new 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>

我的 XSLT 方法:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output indent="yes" method="xml" encoding="utf-8" />

    <!-- Param list -->
    <xsl:param name="key1" select="'My new value'" />
    <xsl:param name="key2" select="'Another value'" />
    <!-- ... more params -->

    <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:stylesheet>

第一次出现的&lt;Note&gt;TESTWORD key1&lt;/Note&gt;&lt;NewElem&gt;My new value&lt;/NewElem&gt; 正确替换。但不是其余的事件。


我可以复制 x 次这幅作品:

<xsl:template match="Note[.='TESTWORD keyX']">
   <xsl:element name="NewElem">
      <xsl:value-of select="$keyX" />
   </xsl:element>
</xsl:template>

但也许有一种迭代方法?


PS:我正在使用 Java

【问题讨论】:

  • 您打算在运行时填充这些参数吗?或者这些值可以在样式表中硬编码吗? (无论哪种方式,您都应该使用 keyw3.org/TR/xslt20/#key
  • @michael.hor257k:键是静态的,值是来自另一个来源的动态。
  • 你能把这些值放在另一个 XML 文档中并从那里读取吗?
  • @michael.hor257k:这需要一个额外的步骤。它们来自 JSON 格式的远程源。
  • @michael.hor257k:将值放入我的 XSLT 文件不是问题。我只是不知道,以后如何迭代这些参数。

标签: xml xslt


【解决方案1】:

使用 Saxon 9.8 及更高版本,您可以声明 XSLT 3/XPath 3.1 类型的参数map(xs:string, xs:string)(即带有字符串键和值的映射)来表示您的键/值对。然后您可以处理它们并在匹配模式中使用它们:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    exclude-result-prefixes="#all"
    version="3.0">
    
  <xsl:param name="map"
             as="map(xs:string, xs:string)"
             select="map { 
                        'key1' : 'My new value',
                        'key2' : 'Another value' 
                    }"/>

  <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]">
      <NewElemen>
          <xsl:value-of select="$map($map-keys[current() = 'TESTWORD ' || .])"/>
      </NewElemen>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/pNmCzsU

在 Java 中,有一些方法可以从类似的 Java 集合构造这样的 XdmMap,例如makeMap (http://saxonica.com/html/documentation9.9/javadoc/net/sf/saxon/s9api/XdmMap.html#makeMap-java.util.Map-) 将 java.util.Map 转换为 XdmMap。

建议使用 Saxon 9.8 或更高版本的 s9api 和 Xslt30Transformer 来运行 XSLT 3,然后您可以在该类实例上设置参数 wtg http://saxonica.com/html/documentation9.9/javadoc/net/sf/saxon/s9api/Xslt30Transformer.html#setStylesheetParameters-java.util.Map-

但是,如果 Saxon 在类路径中,您也可以使用 JAXP Transformer 传入 XdmMap

    Transformer transformer = TransformerFactory.newInstance().newTransformer(new StreamSource("map-test1.xsl"));
    
    Map<String, String> map1 = new HashMap<>();
    map1.put("key2", "value passed in from JAXP API");
    
    transformer.setParameter("map", XdmMap.makeMap(map1));
    
    transformer.transform(new StreamSource("input-sample1.xml"), new StreamResult(System.out));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 2017-09-20
    • 2015-11-25
    • 1970-01-01
    相关资源
    最近更新 更多