提问人:srgplv 提问时间:6/18/2023 更新时间:6/18/2023 访问量:66
使用 STX 解析器在 XML 中匹配两个不同的块
Matching two different blocks in XML using STX parser
问:
我有一个大的XML文件,我正在尝试使用STX的java joost实现按id匹配两个块。这是我的XML文件:
<?xml version='1.0' encoding='UTF-8'?>
<main>
<table>
<description id="1" size="big" />
<description id="2" size="small" />
<description id="3" size="medium" />
</table>
<products>
<item id="1" color="red" />
<item id="2" color="green" />
<item id="3" color="blue" />
</products>
</main>
这是我尝试创建的输出:
<?xml version='1.0' encoding='UTF-8'?>
<total>
<item id="1" color="red" size="big" />
<item id="2" color="green" size="small" />
<item id="3" color="blue" size="medium" />
</total>
没有给出任何结果,也没有创建类似于 java 的键值对的解决方案。有什么解决办法吗?stx:buffer
HashMap
答:
0赞
Martin Honnen
6/18/2023
#1
我不熟悉 STX,使用标准 XSLT 3.0 流,您可以使用保存地图的累加器:
<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:accumulator name="description" as="map(xs:untypedAtomic, xs:string)" initial-value="map{}" streamable="yes">
<xsl:accumulator-rule match="table/description" select="map:put($value, @id, string(@size))"/>
</xsl:accumulator>
<xsl:mode on-no-match="shallow-copy" use-accumulators="description" streamable="yes"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="main">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="table"/>
<xsl:template match="products">
<total>
<xsl:apply-templates/>
</total>
</xsl:template>
<xsl:template match="item">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="size" select="accumulator-before('description')(@id)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
带有流的 XSLT 3.0 目前似乎只受 Saxon EE(9.8 及更高版本(即 9.9、10、11、12))支持。
我现在尝试构建一个 STX 示例,以下内容似乎有效:
<stx:transform xmlns:stx="http://stx.sourceforge.net/2002/ns" version="1.0"
pass-through="all" strip-space="yes">
<stx:variable name="id"/>
<stx:variable name="size"/>
<stx:template match="table/description">
<stx:assign name="id" select="($id, string(@id))"/>
<stx:assign name="size" select="($size, string(@size))"/>
</stx:template>
<stx:template match="/* | table | table/description">
<stx:process-children/>
</stx:template>
<stx:template match="products">
<total>
<stx:process-children/>
</total>
</stx:template>
<stx:template match="item">
<stx:copy attributes="@*">
<stx:attribute name="size" select="item-at($size, index-of($id, @id))"/>
</stx:copy>
</stx:template>
</stx:transform>
或者使用 Java HashMap:
<stx:transform xmlns:stx="http://stx.sourceforge.net/2002/ns" version="1.0"
xmlns:hm="java:java.util.HashMap"
exclude-result-prefixes="hm"
pass-through="all" strip-space="no">
<stx:variable name="description" select="hm:new()"/>
<stx:template match="table/description">
<stx:variable name="oldValue" select="hm:put($description, string(@id), string(@size))"/>
<!-- <stx:assign name="description" select="$description"/> -->
</stx:template>
<stx:template match="/* | table | table/description">
<stx:process-children/>
</stx:template>
<stx:template match="products">
<total>
<stx:process-children/>
</total>
</stx:template>
<stx:template match="item">
<stx:copy attributes="@*">
<stx:attribute name="size" select="hm:get($description, string(@id))"/>
</stx:copy>
</stx:template>
</stx:transform>
评论
0赞
srgplv
6/18/2023
效果很好!谢谢!
下一个:XSLT 中的特定方案
评论