【问题标题】:Variable in xslt and loopxslt 和循环中的变量
【发布时间】:2019-05-24 10:33:21
【问题描述】:

我有以下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":""
   }
}

description 的值是空的,因为我不知道如何在循环中重新分配变量 description 的值。我使用双循环来获取描述,但效率非常低。

欢迎任何建议

提前致谢。

【问题讨论】:

  • 在 XSLT 中,变量的值一旦定义就无法更改。

标签: java json xml xslt


【解决方案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 的相同选择当然也有助于您的原始代码。

【讨论】:

  • 如何将 添加到您的答案中?
  • 有什么用?假装您使用“循环”而忽略 XSLT 的工作原理?
【解决方案2】:

我在下面修改了您原来的 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    • 1970-01-01
    • 2014-11-09
    • 2015-04-30
    相关资源
    最近更新 更多