XSLT 映射。在 for each 循环中动态设置 xml 节点名称
XSLT mapping. Dynamically setting xml node names in a for each loop
您好,我的 xml 中有重复的节点名称,我想让它们中的每一个都是唯一的。
由于节点数量未知,我想为每个循环实现一个,并使用 XSLT 为每个 UserGroup 节点的名称添加一个计数器。
我正在使用:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
我的输入xml是:
<groups>
<UserGroup>
<integrationKey>xxa</integrationKey>
<uid>001</uid>]
</UserGroup>
<UserGroup>
<integrationKey>xxb</integrationKey>
<uid>002</uid>
</UserGroup>
</groups>
如何使用 XSLT 将 xml 转换为:
<groups>
<UserGroup1>
<integrationKey>xxa</integrationKey>
<uid>001</uid>]
</UserGroup1>
<UserGroup2>
<integrationKey>xxb</integrationKey>
<uid>002</uid>
</UserGroup2>
</groups>
编辑
嗨,原因是我正在处理构建的 xml 消息负载,然后需要将其转换为 JSON(组部分附加到主 xml)。有效载荷将要接受的目标系统接受某种不包括用户组的“格式”。不幸的是,用户组的数量是动态的,映射的控制有限。
我试图在 Groovy 中构建 Json 并使用:
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import groovy.json.JsonBuilder
def body = """
{"B2BCustomer":{"integrationKey":"","customerID":"xxx","email":"xxx","name":"xxx","uid":"xxx","businessUnit":{"BU":{"integrationKey":"","code":"xxx"}},"groups":[{"UserGroup":{"integrationKey":"xxx","uid":"xxx"},"UserGroup":{"integrationKey":"yyy","uid":"yyy"}}]}}"""
//Setup output JSON
def jsonParser = new JsonSlurper();
def jsonObject = jsonParser.parseText(body);
body = JsonOutput.toJson(jsonObject["B2BCustomer"]);
output = jsonParser.parseText(body);
jsonString = jsonParser.parseText(body);
//Create default b2b unit JSON
if(output.containsKey("defaultB2BUnit")){
output.remove("defaultB2BUnit");
defaultB2BUnit = JsonOutput.toJson(jsonString["defaultB2BUnit"]);
jsonObject = jsonParser.parseText(defaultB2BUnit);
defaultB2BUnit = JsonOutput.toJson(jsonObject["B2BUnit"]);
output.put("defaultB2BUnit", defaultB2BUnit);
}
//Create businessUnit JSON
if(output.containsKey("businessUnit")){
output.remove("businessUnit");
businessUnit = JsonOutput.toJson(jsonString["businessUnit"]);
jsonObject = jsonParser.parseText(businessUnit);
businessUnit = JsonOutput.toJson(jsonObject["BU"]);
output.put("businessUnit", businessUnit);
}
//Create groups JSON
if(output.containsKey("groups")){
output.remove("groups");
groups = JsonOutput.toJson(jsonString["groups"]);
jsonObject = jsonParser.parseText(groups);
groups = JsonOutput.toJson(jsonObject["UserGroup"]);
output.put("groups", groups);
}
//Build output JSON
def builder = new JsonBuilder();
builder(output);
def builderString = builder.toString().replace('"{\', '{').replace('\','').replace('}"','}').replace('"[','[').replace(']"',']');
println builderString;
如果键不重复,这会起作用(它只会拉出一个用户组。我的计划是运行这个代码仍然存在,但是组在循环中参与以获得所需的JSON输出。
如果有人有办法让我不必进行字符串替换,那也很棒。很遗憾,我无法更改目标系统元数据的结构。
当前输出:
{
"integrationKey": "",
"customerID": "xxx",
"email": "xxx",
"name": "xxx",
"uid": "xxx",
"businessUnit": {
"integrationKey": "",
"code": "xxx"
},
"groups": [{
"integrationKey": "yyy",
"uid": "yyy"
}
]
}
期望的输出:
{
"integrationKey": "",
"customerID": "xxx",
"email": "xxx",
"name": "xxx",
"uid": "xxx",
"businessUnit": {
"integrationKey": "",
"code": "xxx"
},
"groups": [{
"integrationKey": "xxx",
"uid": "xxx"
},
{
"integrationKey": "yyy",
"uid": "yyy"
}
]
}
额外说明 我正在考虑将组存储在交换 属性 和 运行 自定义 xml -> Json Groovy 脚本来完全按照我想要的方式构建它,而不会受到 JSON slurper 等的奇怪影响。
提前感谢您的努力和建议!
鉴于 XSLT 3,一种方法是使用累加器:
<xsl:accumulator name="UserGroupCounter" as="xs:integer" initial-value="0">
<xsl:accumulator-rule match="groups" select="0"/>
<xsl:accumulator-rule match="groups/UserGroup" select="$value + 1"/>
</xsl:accumulator>
<xsl:template match="UserGroup">
<xsl:element name="{name()}{accumulator-before('UserGroupCounter')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:mode on-no-match="shallow-copy" use-accumulators="UserGroupCounter"/>
我同意关于结果格式不是好的 XML 格式的评论。如果您需要一些元素索引,通常的建议是不要将其放入元素名称中,而是使用属性,例如
<xsl:accumulator name="UserGroupCounter" as="xs:integer" initial-value="0">
<xsl:accumulator-rule match="groups" select="0"/>
<xsl:accumulator-rule match="groups/UserGroup" select="$value + 1"/>
</xsl:accumulator>
<xsl:template match="UserGroup">
<xsl:copy>
<xsl:attribute name="userGroupIndex" select="accumulator-before('UserGroupCounter')"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:mode on-no-match="shallow-copy" use-accumulators="UserGroupCounter"/>
您好,我的 xml 中有重复的节点名称,我想让它们中的每一个都是唯一的。 由于节点数量未知,我想为每个循环实现一个,并使用 XSLT 为每个 UserGroup 节点的名称添加一个计数器。
我正在使用:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
我的输入xml是:
<groups>
<UserGroup>
<integrationKey>xxa</integrationKey>
<uid>001</uid>]
</UserGroup>
<UserGroup>
<integrationKey>xxb</integrationKey>
<uid>002</uid>
</UserGroup>
</groups>
如何使用 XSLT 将 xml 转换为:
<groups>
<UserGroup1>
<integrationKey>xxa</integrationKey>
<uid>001</uid>]
</UserGroup1>
<UserGroup2>
<integrationKey>xxb</integrationKey>
<uid>002</uid>
</UserGroup2>
</groups>
编辑 嗨,原因是我正在处理构建的 xml 消息负载,然后需要将其转换为 JSON(组部分附加到主 xml)。有效载荷将要接受的目标系统接受某种不包括用户组的“格式”。不幸的是,用户组的数量是动态的,映射的控制有限。 我试图在 Groovy 中构建 Json 并使用:
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import groovy.json.JsonBuilder
def body = """
{"B2BCustomer":{"integrationKey":"","customerID":"xxx","email":"xxx","name":"xxx","uid":"xxx","businessUnit":{"BU":{"integrationKey":"","code":"xxx"}},"groups":[{"UserGroup":{"integrationKey":"xxx","uid":"xxx"},"UserGroup":{"integrationKey":"yyy","uid":"yyy"}}]}}"""
//Setup output JSON
def jsonParser = new JsonSlurper();
def jsonObject = jsonParser.parseText(body);
body = JsonOutput.toJson(jsonObject["B2BCustomer"]);
output = jsonParser.parseText(body);
jsonString = jsonParser.parseText(body);
//Create default b2b unit JSON
if(output.containsKey("defaultB2BUnit")){
output.remove("defaultB2BUnit");
defaultB2BUnit = JsonOutput.toJson(jsonString["defaultB2BUnit"]);
jsonObject = jsonParser.parseText(defaultB2BUnit);
defaultB2BUnit = JsonOutput.toJson(jsonObject["B2BUnit"]);
output.put("defaultB2BUnit", defaultB2BUnit);
}
//Create businessUnit JSON
if(output.containsKey("businessUnit")){
output.remove("businessUnit");
businessUnit = JsonOutput.toJson(jsonString["businessUnit"]);
jsonObject = jsonParser.parseText(businessUnit);
businessUnit = JsonOutput.toJson(jsonObject["BU"]);
output.put("businessUnit", businessUnit);
}
//Create groups JSON
if(output.containsKey("groups")){
output.remove("groups");
groups = JsonOutput.toJson(jsonString["groups"]);
jsonObject = jsonParser.parseText(groups);
groups = JsonOutput.toJson(jsonObject["UserGroup"]);
output.put("groups", groups);
}
//Build output JSON
def builder = new JsonBuilder();
builder(output);
def builderString = builder.toString().replace('"{\', '{').replace('\','').replace('}"','}').replace('"[','[').replace(']"',']');
println builderString;
如果键不重复,这会起作用(它只会拉出一个用户组。我的计划是运行这个代码仍然存在,但是组在循环中参与以获得所需的JSON输出。
如果有人有办法让我不必进行字符串替换,那也很棒。很遗憾,我无法更改目标系统元数据的结构。
当前输出:
{
"integrationKey": "",
"customerID": "xxx",
"email": "xxx",
"name": "xxx",
"uid": "xxx",
"businessUnit": {
"integrationKey": "",
"code": "xxx"
},
"groups": [{
"integrationKey": "yyy",
"uid": "yyy"
}
]
}
期望的输出:
{
"integrationKey": "",
"customerID": "xxx",
"email": "xxx",
"name": "xxx",
"uid": "xxx",
"businessUnit": {
"integrationKey": "",
"code": "xxx"
},
"groups": [{
"integrationKey": "xxx",
"uid": "xxx"
},
{
"integrationKey": "yyy",
"uid": "yyy"
}
]
}
额外说明 我正在考虑将组存储在交换 属性 和 运行 自定义 xml -> Json Groovy 脚本来完全按照我想要的方式构建它,而不会受到 JSON slurper 等的奇怪影响。 提前感谢您的努力和建议!
鉴于 XSLT 3,一种方法是使用累加器:
<xsl:accumulator name="UserGroupCounter" as="xs:integer" initial-value="0">
<xsl:accumulator-rule match="groups" select="0"/>
<xsl:accumulator-rule match="groups/UserGroup" select="$value + 1"/>
</xsl:accumulator>
<xsl:template match="UserGroup">
<xsl:element name="{name()}{accumulator-before('UserGroupCounter')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:mode on-no-match="shallow-copy" use-accumulators="UserGroupCounter"/>
我同意关于结果格式不是好的 XML 格式的评论。如果您需要一些元素索引,通常的建议是不要将其放入元素名称中,而是使用属性,例如
<xsl:accumulator name="UserGroupCounter" as="xs:integer" initial-value="0">
<xsl:accumulator-rule match="groups" select="0"/>
<xsl:accumulator-rule match="groups/UserGroup" select="$value + 1"/>
</xsl:accumulator>
<xsl:template match="UserGroup">
<xsl:copy>
<xsl:attribute name="userGroupIndex" select="accumulator-before('UserGroupCounter')"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:mode on-no-match="shallow-copy" use-accumulators="UserGroupCounter"/>