【问题标题】:XSLT: Convert Name/Value pair and transform an XMLXSLT:转换名称/值对并转换 XML
【发布时间】:2017-09-30 12:25:39
【问题描述】:

我需要将名称值对转换为 XML。我能够生成 XML,但元素名称应该被分组并且不应该重复。请看下文。 FieldValue 元素在 Detail 节点中包含 2 个 OrderItem 值。如果带有 OrderItem 的 FieldValue 重复,则应将结果分组到一个 OrderItem 节点中。请帮忙。

源 XML:

<SC>
	<Header>
		<Record>
			<FieldName>Schema</FieldName>
			<FieldValue>OrderHeader</FieldValue>
		</Record>
		<Record>
			<FieldName>Order</FieldName>
			<FieldValue>1234</FieldValue>
		</Record>
	</Header>
	<Detail>
		<Record>
			<FieldName>Schema</FieldName>
			<FieldValue>OrderItem</FieldValue>
		</Record>
		<Record>
			<FieldName>Item</FieldName>
			<FieldValue>1</FieldValue>
		</Record>
		<Record>
			<FieldName>Qty</FieldName>
			<FieldValue>10</FieldValue>
		</Record>
	</Detail>
	<Detail>
		<Record>
			<FieldName>Schema</FieldName>
			<FieldValue>OrderItem</FieldValue>
		</Record>
		<Record>
			<FieldName>Item</FieldName>
			<FieldValue>2</FieldValue>
		</Record>
		<Record>
			<FieldName>Qty</FieldName>
			<FieldValue>20</FieldValue>
		</Record>
	</Detail>
</SC>

目标 XML:

<Order>
 <OrderItem>
   <Item>
      <Item>1</Item>
      <Qty>10</Qty>
   </Item>
   <Item>
      <Item>2</Item>
      <Qty>20</Qty>
   </Item>
 </OrderItem>
</Order>

XSLT:

<xsl:template match="@*|node()">
<Order>
    <xsl:for-each select="Detail">
        <Item>
            <xsl:apply-templates select="Record[position()>1]"/>
        </Item>
</xsl:for-each>
</Order>
</xsl:template>

<xsl:template match="Record">
    <xsl:element name="{FieldName}">
        <xsl:value-of select="FieldValue"/>
    </xsl:element>
</xsl:template>

【问题讨论】:

    标签: xslt-1.0 xslt-2.0


    【解决方案1】:

    分组可以如下进行:

    <?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"
        exclude-result-prefixes="xs"
        version="2.0">
    
        <xsl:output indent="yes"/>
    
        <xsl:template match="SC">
            <Order>
                <xsl:for-each-group select="Detail" group-by="Record[1]/FieldValue">
                    <xsl:element name="{current-grouping-key()}">
                        <xsl:apply-templates select="current-group()"/>
                    </xsl:element>
                </xsl:for-each-group>
            </Order>
        </xsl:template>
    
        <xsl:template match="Detail">
            <Item>
                <xsl:apply-templates select="Record[position() gt 1]"/>
            </Item>
        </xsl:template>
    
        <xsl:template match="Record">
            <xsl:element name="{FieldName}">
                <xsl:value-of select="FieldValue"/>
            </xsl:element>
        </xsl:template>
    
    </xsl:stylesheet>
    

    【讨论】:

      【解决方案2】:

      您似乎正试图定义两个 XSLT 模板,而一个应该就足够了。你想在根上匹配,然后你想遍历每个SC/Detail

      然后,您要获取 FieldName 节点的兄弟节点的 FieldValue,即“Item”(用于项目值)和“Qty”(用于数量值),但仅适用于“记录”下列出的那些。

      注意:您已在转换后的输出中指定了双重嵌套的&lt;Item&gt;,此解决方案反映了该要求。

      此 XSLT 应该满足您的要求:

      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:template match="/">
        <xsl:for-each select="SC/Detail">
      <Order>
        <OrderItem>
          <Item>
          <Item>
            <xsl:value-of select="Record[FieldName[text()='Item']]/FieldValue" />
          </Item>
          <Qty>
            <xsl:value-of select="Record[FieldName[text()='Qty']]/FieldValue" />
          </Qty>
          </Item>
        </OrderItem>
      </Order>
      </xsl:for-each>
      </xsl:template>
      
      </xsl:stylesheet>
      

      【讨论】:

      • 您好,感谢您的意见。 OrderItem 元素应根据名称值对动态创建。元素/节点不是静态的。它是动态的。
      • 您的问题中提供的代码中并不清楚该要求。如果您可以更新您的问题(即,准确更新您期望目标 XML 的样子),那么我可以为您更新我的答案。
      猜你喜欢
      • 2014-12-21
      • 1970-01-01
      • 1970-01-01
      • 2019-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-11
      相关资源
      最近更新 更多