如何使用XSLT将节点位置编号作为元素附加到XML?

时间:2018-08-08 20:06:24

标签: javascript html xml xslt

我有以下XML,需要按照下面“期望的输出”部分中的说明进行转换。

转换的要求是:

  1. 同属节点(例如,从属和位置)需要附加其对应的位置ID,例如...如果文件中存在多个从属节点,则节点应显示为,等等。
  2. 需要将兄弟节点的位置作为单独的元素名称插入其相应的子节点下

示例XML输入文件

<?xml version="1.0" encoding="UTF-8"?>
<workers>
	<worker>
		<name>sam</name>
		<batch_id>1345</batch_id>
		<dependents>
			<name>sara</name>
		</dependents>
		<dependents>
			<name>tom</name>
		</dependents>
		<dependents>
			<name>harry</name>
		</dependents>
		<locations>
			<place>ny</place>
			<type>work</type>
		</locations>
		<locations>
			<place>sfo</place>
			<type>home</type>
		</locations>
	</worker>
</workers>

预期产量

<?xml version="1.0" encoding="UTF-8"?>
<workers>
	<worker>
		<name>sam</name>
		<batch_id>1345</batch_id>
		<dependents1>
			<name>sara</name>
		</dependents1>
		<dependents_row1>1</dependents_row1>
		<dependents2>
			<name>tom</name>
		</dependents2>
		<dependents_row2>2</dependents_row2>
		<dependents3>
			<name>harry</name>
		</dependents3>
		<dependents_row3>3</dependents_row3>
		<locations1>
			<place>ny</place>
			<type>work</type>
		</locations1>
		<locations_row1>1</locations_row1>
		<locations2>
			<place>sfo</place>
			<type>home</type>
		</locations2>
		<locations_row2>2</locations_row2>
	</worker>
</workers>

2 个答案:

答案 0 :(得分:1)

您可以使用以下样式表(尽管有给定的设计疑问):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />

    <!-- identity template -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/workers/worker">           <!-- handles the sub-elements of the worker node -->
        <xsl:copy>
            <xsl:apply-templates select="*[not(self::dependents or self::locations)]" />   
            <xsl:apply-templates select="dependents" />   
            <xsl:apply-templates select="locations" />   
        </xsl:copy>
    </xsl:template>

    <xsl:template match="dependents|locations">      <!-- handles the addition of the position nodes -->
        <xsl:element name="{concat(local-name(),position())}">
            <xsl:copy-of select="*" />
        </xsl:element>
        <xsl:element name="{concat(local-name(),'_row',position())}">
            <xsl:value-of select="position()" />
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

一种不知道元素名称并且使用注释中建议的xsl:number的通用解决方案是

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs">

  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

  <xsl:template match="*[some $sibling in (preceding-sibling::*, following-sibling::*) satisfies node-name($sibling) = node-name(.)]">
      <xsl:variable name="index" as="xs:integer">
          <xsl:number/>
      </xsl:variable>
      <xsl:element name="{name()}{$index}">
          <xsl:apply-templates/>
      </xsl:element>
      <xsl:element name="{name()}_row{$index}">
          <xsl:value-of select="$index"/>
      </xsl:element>
  </xsl:template>

</xsl:transform>

当然,您可以将match="*[some $sibling in (preceding-sibling::*, following-sibling::*) satisfies node-name($sibling) = node-name(.)]"简化或简化为match="descendents | locations",如果已知元素和/或仅将某些元素作为目标。

http://xsltransform.hikmatu.com/6qM2e2o/2