我有以下xml
<Request>
<Record>
<ID>123456789</ID>
<OtherID>ABC123</OtherID>
<Title>Example</Title>
<Properties>
<Attribute type="Main">
<Name>Description</Name>
<Value>This is an example</Value>
</Attribute>
<Attribute type="Main">
<Name>Source</Name>
<Value>A1</Value>
</Attribute>
<Attribute type="Main">
<Name>Source</Name>
<Value>B</Value>
</Attribute>
<Attribute type="Main">
<Name>Represenative</Name>
<Value>Mike</Value>
</Attribute>
<Attribute type="Main">
<Name>Animal</Name>
<Value>Elephant</Value>
</Attribute>
</Properties>
</Record>
</Request>
我想要以下json。
{
"Record":{
"ID":"123456789",
"OtherID":"ABC123",
"Title":"Example",
"Properties":[
{
"Type":"Main",
"Value":"Source",
"Name":"A1"
},
{
"Type":"Main",
"Value":"Source",
"Name":"B"
},
{
"Type":"Main",
"Value":"Representative",
"Name":"Mike"
},
{
"Type":"Main",
"Value":"Animal",
"Name":"Elephant"
}
],
"Description":"This is an example"
}
}
请注意,description属性不是数组的一部分,它与属性,ID,OtherID和Title处于同一级别。
我正在应用以下xslt将xml转换为json。在此xml中,我声明了一个变量,该变量将包含说明并将其添加到对象的末尾
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:variable name="description2" select="''" />
{
<xsl:for-each select="Request/Record">
"Record": {
"ID":"<xsl:value-of select="ID" />",
"OtherId": "<xsl:value-of select="OtherID" />",
"Title":"Example",
<xsl:if test="Properties">
"Properties": [
<xsl:for-each select="Properties/Attribute">
<xsl:if test="soi:Name = 'Description'">
<xsl:variable name="description2" select="<xsl:value-of select="Value" />" />
<xsl:if test="position() != last()">,</xsl:if>
</xsl:if>
<xsl:if test="Name != 'Description'">
{
"Type": "Main",
"Name": "<xsl:value-of select="Name" />",
"Value": "<xsl:value-of select="Value" />"
}
<xsl:if test="position() != last()">,</xsl:if>
</xsl:if>
</xsl:for-each>
]
</xsl:if>
}<xsl:if test="position() != last()">,</xsl:if>
</xsl:for-each>
<xsl:if test="description2!=''">
,"Description":"<xsl:value-of select="$description2"/>"
</xsl:if>
}
</xsl:template>
不幸的是,我得到了这个输出
{
"Request":{
"ID":"123456789",
"OtherID":"ABC123",
"Title":"Example",
"Properties":[
{
"Type":"Main",
"Value":"Source",
"Name":"A1"
},
{
"Type":"Main",
"Value":"Source",
"Name":"B"
},
{
"Type":"Main",
"Value":"Representative",
"Name":"Mike"
},
{
"Type":"Main",
"Value":"Animal",
"Name":"Elephant"
}
],
"Description":""
}
}
描述的值是空的,因为我不知道如何在循环中重新分配变量描述的值。我使用了一个双循环来获取描述,但是效率很低。
欢迎任何建议
谢谢。
答案 0 :(得分:1)
在XSLT 3(随Saxon 9.8或更高版本以及AltovaXML 2017 R3和更高版本中提供)中,您可以简单地将XML转换为xml-to-json
函数https://www.w3.org/TR/xpath-functions/#func-xml-to-json期望的XML格式,然后应用该函数:
<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"
xmlns="http://www.w3.org/2005/xpath-functions"
expand-text="yes"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="text"/>
<xsl:template match="Request">
<xsl:variable name="json-xml">
<map>
<xsl:apply-templates/>
</map>
</xsl:variable>
<xsl:value-of select="xml-to-json($json-xml, map { 'indent' : true() })"/>
</xsl:template>
<xsl:template match="Record">
<map key="{local-name()}">
<xsl:apply-templates/>
</map>
</xsl:template>
<xsl:template match="ID | OtherID | Title">
<string key="{local-name()}">{.}</string>
</xsl:template>
<xsl:template match="Properties">
<array key="{local-name()}">
<xsl:apply-templates select="Attribute[not(Name = 'Description')]"/>
</array>
<string key="Description">{Attribute[Name = 'Description']/Value}</string>
</xsl:template>
<xsl:template match="Attribute">
<map>
<xsl:apply-templates select="@type, Value, Name"/>
</map>
</xsl:template>
<xsl:template match="Attribute/@* | Attribute/*">
<string key="{local-name()}">{.}</string>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bnnZWz/2
使用相同的选项来区分Attribute[not(Name = 'Description')]
和Attribute[Name = 'Description']/Value
当然也会对您的原始代码有所帮助。
答案 1 :(得分:0)
我已经在下面修改了您的原始XSLT,以便填充“说明”的值。
我注释掉了与变量$ description2相关的部分。我没有使用变量,而是使用XPath选择其中[../ Name ='Description']
的元素。祝你好运!
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text" />
<xsl:template match="/">
<!--<xsl:variable name="description2" select="''" />-->
{
<xsl:for-each select="Request/Record">
"Record": {
"ID":"<xsl:value-of select="ID" />",
"OtherId": "<xsl:value-of select="OtherID" />",
"Title":"Example",
<xsl:if test="Properties">
"Properties": [
<xsl:for-each select="Properties/Attribute">
<!--<xsl:if test="soi:Name = 'Description'">
<xsl:variable name="description2" select="<xsl:value-of select="Value" />" />
<xsl:if test="position() != last()">,</xsl:if>
</xsl:if>-->
<xsl:if test="Name != 'Description'">
{
"Type": "Main",
"Name": "<xsl:value-of select="Name" />",
"Value": "<xsl:value-of select="Value" />"
}
<xsl:if test="position() != last()">,</xsl:if>
</xsl:if>
</xsl:for-each>
]
</xsl:if>
}<xsl:if test="position() != last()">,</xsl:if>
</xsl:for-each>
<xsl:if test="/Request/Record/Properties/Attribute/Value[../Name='Description']">
,"Description":"<xsl:value-of select="/Request/Record/Properties/Attribute/Value[../Name='Description']"/>"
</xsl:if>
}
</xsl:template>
</xsl:stylesheet>