Xml Xsl:父节点和属性节点的编号
前任职位- 感谢Martin,我正在完成基于相同代码的后续项目。在这个项目中,我需要能够增加父节点的数量,以基于原始节点创建某种关系的xml输出。我还需要为属性创建与当前节点相关的关系 预期结果摘要Xml Xsl:父节点和属性节点的编号,xml,xslt,xpath,Xml,Xslt,Xpath,前任职位- 感谢Martin,我正在完成基于相同代码的后续项目。在这个项目中,我需要能够增加父节点的数量,以基于原始节点创建某种关系的xml输出。我还需要为属性创建与当前节点相关的关系 预期结果摘要 将所有节点列为已完成 a) 将所有父节点列为子关系的ID字段- 完成 b) 将所有子节点(没有子节点的最低级别节点)列为已完成 c) 将所有属性列为: i) 如果不存在子节点-无法 为父节点拉### ii)如果存在子节点-无法为父节点拉#### 输入xml: <xml> &l
- 将所有节点列为已完成
- a) 将所有父节点列为子关系的ID字段- 完成
- b) 将所有子节点(没有子节点的最低级别节点)列为已完成
- c) 将所有属性列为:
- i) 如果不存在子节点-无法 为父节点拉###
- ii)如果存在子节点-无法为父节点拉####
<xml>
<individual attr="test" attr2="test3" attr3="test2">
<name>
<firstname seq="1">Me</firstname>
<lastname>Last</lastname>
</name>
<addresses>
<address>
<street>1234 Main</street>
<city>Anytown</city>
<state>TX</state>
</address>
<address>
<street>4321 Central Ave</street>
<city>Bixby</city>
<state>ND</state>
</address>
</addresses>
<employeers>
<employeer>
<name>
<firstname seq3="99">Employer1</firstname>
<lastname>EmployerLast</lastname>
</name>
<addresses>
<address>
<street>1234 Employer1</street>
<city>Smallville</city>
<state>CT</state>
</address>
</addresses>
</employeer>
<employeer attr="test" attr2="test3" attr3="test2">
<name>
<firstname>Employer2</firstname>
<lastname>EmployerLast2</lastname>
</name>
<addresses>
<address>
<street>1234 Employer2</street>
<city>Nashville</city>
<state>TN</state>
</address>
</addresses>
</employeer>
</employeers>
</individual>
</xml>
我
最后
实际结果与预期结果:
<?xml version="1.0" encoding="utf-16"?>
<KEY name="individual_001_ParentID" value="xml_001" />
<KEY name="individual_001_attr" value="test" />
<KEY name="individual_001_attr2" value="test3" />
<KEY name="individual_001_attr3" value="test2" />
<KEY name="name_001_ParentID" value="individual_001" />
<KEY name="name_001_firstname" value="Me" />
<KEY name="name_001_firstname_seq" value="1" />
<KEY name="name_001_lastname" value="Last" />
<KEY name="addresses_001_ParentID" value="individual_001" />
<KEY name="address_001_ParentID" value="addresses_001" />
<KEY name="address_001_street" value="1234 Main" />
<KEY name="address_001_city" value="Anytown" />
<KEY name="address_001_state" value="TX" />
<KEY name="address_002_ParentID" value="addresses_002" />
<KEY name="address_002_street" value="4321 Central Ave" />
<KEY name="address_002_city" value="Bixby" />
<KEY name="address_002_state" value="ND" />
<KEY name="employeers_001_ParentID" value="individual_001" />
<KEY name="employeer_001_ParentID" value="employeers_001" />
<KEY name="name_002_ParentID" value="employeer_002" />
<KEY name="name_002_firstname" value="Employer1" />
<!-- actual result -->
<KEY name="name_001_firstname_seq3" value="99" />
<!-- desired result as this is the secod occurrance of the parent node-->
<KEY name="name_002_firstname_seq3" value="99" />
<KEY name="name_002_lastname" value="EmployerLast" />
<KEY name="addresses_002_ParentID" value="employeer_002" />
<KEY name="address_003_ParentID" value="addresses_003" />
<KEY name="address_003_street" value="1234 Employer1" />
<KEY name="address_003_city" value="Smallville" />
<KEY name="address_003_state" value="CT" />
<KEY name="employeer_002_ParentID" value="employeers_002" />
<!-- actual result -->
<KEY name="employeer_001_attr" value="test" />
<KEY name="employeer_001_attr2" value="test3" />
<KEY name="employeer_001_attr3" value="test2" />
<!-- desired result as this is the secod occurrance of the parent node-->
<KEY name="employeer_002_attr" value="test" />
<KEY name="employeer_002_attr2" value="test3" />
<KEY name="employeer_002_attr3" value="test2" />
<KEY name="name_003_ParentID" value="employeer_003" />
<KEY name="name_003_firstname" value="Employer2" />
<KEY name="name_003_lastname" value="EmployerLast2" />
<KEY name="addresses_003_ParentID" value="employeer_003" />
<KEY name="address_004_ParentID" value="addresses_004" />
<KEY name="address_004_street" value="1234 Employer2" />
<KEY name="address_004_city" value="Nashville" />
<KEY name="address_004_state" value="TN" />
如果我们将编号保存在变量中,例如
<xsl:variable name="first_count">
<xsl:number format="001" level="any"/>
</xsl:variable>
我们可以达到你想要的结果。修改后的样式表如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output omit-xml-declaration="no" method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="/*//*[*]">
<xsl:variable name="first_count">
<xsl:number format="001" level="any"/>
</xsl:variable>
<xsl:element name="KEY">
<xsl:attribute name="name">
<xsl:value-of select="local-name()"/>_<xsl:value-of select="$first_count"/>_ParentID</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="name(..)"/>_<xsl:value-of select="$first_count"/>
</xsl:attribute>
</xsl:element>
<xsl:for-each select="@*">
<xsl:element name="KEY">
<!-- Trying to get the output to list:
1) the current node and increment - issue
2) the current attribute -->
<xsl:attribute name="name">
<xsl:value-of select="name(..)"/>_<xsl:value-of select="$first_count"/>_<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="//*[not(*)]">
<xsl:variable name="second_count">
<xsl:number format="001" level="any"/>
</xsl:variable>
<xsl:element name="KEY">
<!-- Trying to get the output to list:
1) the parent node and increment - issue
2) the current node -->
<xsl:attribute name="name">
<xsl:value-of select="name(..)"/>_<xsl:value-of select="$second_count"/>_<xsl:value-of select="local-name()"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="current()"/>
</xsl:attribute>
</xsl:element>
<xsl:for-each select="@*">
<xsl:element name="KEY">
<!-- Trying to get the output to list:
1) the parent node and increment - issue
2) the current node
3) the current attribute -->
<xsl:attribute name="name">
<xsl:value-of select="name(../..)"/>_<xsl:value-of select="$second_count"/>_<xsl:value-of select="name(..)"/>_<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
__父ID
_
__
__
___
如果我们将编号保存在变量中,如
<xsl:variable name="first_count">
<xsl:number format="001" level="any"/>
</xsl:variable>
我们可以达到你想要的结果。修改后的样式表如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output omit-xml-declaration="no" method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="/*//*[*]">
<xsl:variable name="first_count">
<xsl:number format="001" level="any"/>
</xsl:variable>
<xsl:element name="KEY">
<xsl:attribute name="name">
<xsl:value-of select="local-name()"/>_<xsl:value-of select="$first_count"/>_ParentID</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="name(..)"/>_<xsl:value-of select="$first_count"/>
</xsl:attribute>
</xsl:element>
<xsl:for-each select="@*">
<xsl:element name="KEY">
<!-- Trying to get the output to list:
1) the current node and increment - issue
2) the current attribute -->
<xsl:attribute name="name">
<xsl:value-of select="name(..)"/>_<xsl:value-of select="$first_count"/>_<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="//*[not(*)]">
<xsl:variable name="second_count">
<xsl:number format="001" level="any"/>
</xsl:variable>
<xsl:element name="KEY">
<!-- Trying to get the output to list:
1) the parent node and increment - issue
2) the current node -->
<xsl:attribute name="name">
<xsl:value-of select="name(..)"/>_<xsl:value-of select="$second_count"/>_<xsl:value-of select="local-name()"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="current()"/>
</xsl:attribute>
</xsl:element>
<xsl:for-each select="@*">
<xsl:element name="KEY">
<!-- Trying to get the output to list:
1) the parent node and increment - issue
2) the current node
3) the current attribute -->
<xsl:attribute name="name">
<xsl:value-of select="name(../..)"/>_<xsl:value-of select="$second_count"/>_<xsl:value-of select="name(..)"/>_<xsl:value-of select="name()"/>
</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
__父ID
_
__
__
___
至少在XSLT 2或3中,您还可以将编号更改为,例如
<xsl:attribute name="name">
<xsl:value-of select="name(..)"/>_<xsl:number format="001" select=".." level="any"/>_<xsl:value-of select="name()"/>
</xsl:attribute>
__
要计算属性的父元素,请参见
至少在XSLT 2或3中,您还可以将编号更改为,例如
<xsl:attribute name="name">
<xsl:value-of select="name(..)"/>_<xsl:number format="001" select=".." level="any"/>_<xsl:value-of select="name()"/>
</xsl:attribute>
__
要计算属性的父元素,请参见
我认为,通过在变量中捕获名称/编号,并将其作为参数传递到应用模板中,可以稍微简化样式表
您还应该能够对没有子元素的所有属性和元素使用单个模板
似乎也没有理由使用xsl:element
而不是创建文本结果元素
我一直在使用local-name()
。如果需要包含任何名称空间前缀,请改用name()
我还使用了XSLT2.0,因为它是样式表中指定的版本。在下面的示例链接中,我将引擎改为Saxon HE,而不是MS XslCompiledTransform(1.0处理器)
XSLT2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*" priority="1">
<xsl:apply-templates select="@*|*"/>
</xsl:template>
<xsl:template match="*">
<xsl:param name="parentInfo"/>
<xsl:variable name="nbr">
<xsl:number format="000" level="any"/>
</xsl:variable>
<xsl:variable name="parentNbr">
<xsl:number format="000" level="any" select=".."/>
</xsl:variable>
<KEY
name="{string-join((local-name(),$nbr,'ParentID'),'_')}"
value="{string-join((local-name(..),$parentNbr),'_')}"/>
<xsl:apply-templates select="@*,*">
<xsl:with-param name="parentInfo"
select="string-join((local-name(),$nbr),'_')"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="@*|*[not(*)]">
<xsl:param name="parentInfo"/>
<KEY
name="{string-join((
if (self::attribute() and not(../../*[*])) then
($parentInfo,local-name(..)) else $parentInfo,
local-name()),'_')}"
value="{.}"
/>
<xsl:apply-templates select="@*">
<xsl:with-param name="parentInfo" select="$parentInfo"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
输出
<KEY name="individual_001_ParentID" value="xml_001"/>
<KEY name="individual_001_attr" value="test"/>
<KEY name="individual_001_attr2" value="test3"/>
<KEY name="individual_001_attr3" value="test2"/>
<KEY name="name_001_ParentID" value="individual_001"/>
<KEY name="name_001_firstname" value="Me"/>
<KEY name="name_001_firstname_seq" value="1"/>
<KEY name="name_001_lastname" value="Last"/>
<KEY name="addresses_001_ParentID" value="individual_001"/>
<KEY name="address_001_ParentID" value="addresses_001"/>
<KEY name="address_001_street" value="1234 Main"/>
<KEY name="address_001_city" value="Anytown"/>
<KEY name="address_001_state" value="TX"/>
<KEY name="address_002_ParentID" value="addresses_001"/>
<KEY name="address_002_street" value="4321 Central Ave"/>
<KEY name="address_002_city" value="Bixby"/>
<KEY name="address_002_state" value="ND"/>
<KEY name="employeers_001_ParentID" value="individual_001"/>
<KEY name="employeer_001_ParentID" value="employeers_001"/>
<KEY name="name_002_ParentID" value="employeer_001"/>
<KEY name="name_002_firstname" value="Employer1"/>
<KEY name="name_002_firstname_seq3" value="99"/>
<KEY name="name_002_lastname" value="EmployerLast"/>
<KEY name="addresses_002_ParentID" value="employeer_001"/>
<KEY name="address_003_ParentID" value="addresses_002"/>
<KEY name="address_003_street" value="1234 Employer1"/>
<KEY name="address_003_city" value="Smallville"/>
<KEY name="address_003_state" value="CT"/>
<KEY name="employeer_002_ParentID" value="employeers_001"/>
<KEY name="employeer_002_attr" value="test"/>
<KEY name="employeer_002_attr2" value="test3"/>
<KEY name="employeer_002_attr3" value="test2"/>
<KEY name="name_003_ParentID" value="employeer_002"/>
<KEY name="name_003_firstname" value="Employer2"/>
<KEY name="name_003_lastname" value="EmployerLast2"/>
<KEY name="addresses_003_ParentID" value="employeer_002"/>
<KEY name="address_004_ParentID" value="addresses_003"/>
<KEY name="address_004_street" value="1234 Employer2"/>
<KEY name="address_004_city" value="Nashville"/>
<KEY name="address_004_state" value="TN"/>
工作实例:
我认为,通过在变量中捕获名称/编号,并将其作为参数传递到应用模板中,可以稍微简化样式表
您还应该能够对没有子元素的所有属性和元素使用单个模板
似乎也没有理由使用xsl:element
而不是创建文本结果元素
我一直在使用local-name()
。如果需要包含任何名称空间前缀,请改用name()
我还使用了XSLT2.0,因为它是样式表中指定的版本。在下面的示例链接中,我将引擎改为Saxon HE,而不是MS XslCompiledTransform(1.0处理器)
XSLT2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*" priority="1">
<xsl:apply-templates select="@*|*"/>
</xsl:template>
<xsl:template match="*">
<xsl:param name="parentInfo"/>
<xsl:variable name="nbr">
<xsl:number format="000" level="any"/>
</xsl:variable>
<xsl:variable name="parentNbr">
<xsl:number format="000" level="any" select=".."/>
</xsl:variable>
<KEY
name="{string-join((local-name(),$nbr,'ParentID'),'_')}"
value="{string-join((local-name(..),$parentNbr),'_')}"/>
<xsl:apply-templates select="@*,*">
<xsl:with-param name="parentInfo"
select="string-join((local-name(),$nbr),'_')"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="@*|*[not(*)]">
<xsl:param name="parentInfo"/>
<KEY
name="{string-join((
if (self::attribute() and not(../../*[*])) then
($parentInfo,local-name(..)) else $parentInfo,
local-name()),'_')}"
value="{.}"
/>
<xsl:apply-templates select="@*">
<xsl:with-param name="parentInfo" select="$parentInfo"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
输出
<KEY name="individual_001_ParentID" value="xml_001"/>
<KEY name="individual_001_attr" value="test"/>
<KEY name="individual_001_attr2" value="test3"/>
<KEY name="individual_001_attr3" value="test2"/>
<KEY name="name_001_ParentID" value="individual_001"/>
<KEY name="name_001_firstname" value="Me"/>
<KEY name="name_001_firstname_seq" value="1"/>
<KEY name="name_001_lastname" value="Last"/>
<KEY name="addresses_001_ParentID" value="individual_001"/>
<KEY name="address_001_ParentID" value="addresses_001"/>
<KEY name="address_001_street" value="1234 Main"/>
<KEY name="address_001_city" value="Anytown"/>
<KEY name="address_001_state" value="TX"/>
<KEY name="address_002_ParentID" value="addresses_001"/>
<KEY name="address_002_street" value="4321 Central Ave"/>
<KEY name="address_002_city" value="Bixby"/>
<KEY name="address_002_state" value="ND"/>
<KEY name="employeers_001_ParentID" value="individual_001"/>
<KEY name="employeer_001_ParentID" value="employeers_001"/>
<KEY name="name_002_ParentID" value="employeer_001"/>
<KEY name="name_002_firstname" value="Employer1"/>
<KEY name="name_002_firstname_seq3" value="99"/>
<KEY name="name_002_lastname" value="EmployerLast"/>
<KEY name="addresses_002_ParentID" value="employeer_001"/>
<KEY name="address_003_ParentID" value="addresses_002"/>
<KEY name="address_003_street" value="1234 Employer1"/>
<KEY name="address_003_city" value="Smallville"/>
<KEY name="address_003_state" value="CT"/>
<KEY name="employeer_002_ParentID" value="employeers_001"/>
<KEY name="employeer_002_attr" value="test"/>
<KEY name="employeer_002_attr2" value="test3"/>
<KEY name="employeer_002_attr3" value="test2"/>
<KEY name="name_003_ParentID" value="employeer_002"/>
<KEY name="name_003_firstname" value="Employer2"/>
<KEY name="name_003_lastname" value="EmployerLast2"/>
<KEY name="addresses_003_ParentID" value="employeer_002"/>
<KEY name="address_004_ParentID" value="addresses_003"/>
<KEY name="address_004_street" value="1234 Employer2"/>
<KEY name="address_004_city" value="Nashville"/>
<KEY name="address_004_state" value="TN"/>
工作实例:
考虑将所需输出添加到问题中。添加的实际结果与所需结果考虑将所需输出添加到问题中。添加的实际结果与所需结果虽然在有限的示例中有效,但在我的实际数据中不起作用,如最后4行所示。所有这些都应该是关于_VERSION _002而不是001的。虽然这在有限的示例中有效,但在我的实际数据中不起作用,如最后4行所示。所有这些都应该是关于_VERSION _002而不是001的。虽然这在有限的示例中有效,但在我的实际数据中不起作用,如最后4行所示。所有这些都应该是关于_VERSION _002而不是001的。虽然这在有限的示例中有效,但在我的实际数据中不起作用,如最后4行所示。所有这些都应该是关于_版本_002而不是001的。谢谢您的简化。现在