使用基于 "name" 属性的 XSLT 重命名 XML 节点
Renaming XML nodes with XSLT based on "name" attribute
我有这个xml:
<?xml version="1.0" encoding="utf-8"?>
<Document Id="0c744468-67d8-4daa-8ff9-cbd23209c59d" Name="ROW_Easement (1)" TypeId="adde4dc1-0710-452a-82c7-9e5ac1bafe94" TypeName="ROW_Easement" OriginalName="106-19-47A.pdf" MimeType="application/pdf">
<Field Name="File Name" Confidence="1.00" Page="1" Valid="True">106-19-47A</Field>
<Section Name="tblPersonOfInterest">
<SectionCollection Name="From" Count="4">
<Section Name="From 1">
<Field Name="Grantor" Confidence="1.00" Page="1" Valid="True" Location="1.713, 8.200, 6.487, 0.500">MARY E. GIBSON, and husband, E. J. GIBSON;
ROSALIE L. SIEN, and husband, A. C. SIEN, Jr</Field>
</Section>
</SectionCollection>
</Section>
</Document>
我想用“名称”属性值替换所有节点名称。到目前为止我有:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<ROW_Easement>
<xsl:for-each select="Field">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:value-of select="self::node()" />
</xsl:element>
</xsl:for-each>
<xsl:for-each select="Section">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:value-of select="self::node()" />
</xsl:element>
</xsl:for-each>
<xsl:for-each select="SectionCollection">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:value-of select="self::node()" />
</xsl:element>
</xsl:for-each>
</ROW_Easement>
</xsl:template>
</xsl:stylesheet>
结果是:
<?xml version="1.0" encoding="utf-8"?>
<ROW_Easement>
<File_Name>106-19-47A</File_Name>
<tblPersonOfInterest>
MARY E. GIBSON, and husband, E. J. GIBSON;
ROSALIE L. SIEN, and husband, A. C. SIEN, Jr
</tblPersonOfInterest>
</ROW_Easement>
它在 SectionCollection 节点中断,但我不明白为什么。
根据@michael.hor257k 的建议更新
更新:使用我现在得到的第一个建议:
<?xml version="1.0" encoding="utf-8"?><ROW_Easement>0c744468-67d8-4daa-8ff9-cbd23209c59dROW_Easement (1)adde4dc1-0710-452a-82c7-9e5ac1bafe94ROW_Easement106-19-47A.pdfapplication/pdf
<File_Name>1.001True106-19-47A</File_Name>
<tblPersonOfInterest>
<From>4
<From_1>
<Grantor>1.001True1.713, 8.200, 6.487, 0.500MARY E. GIBSON, and husband, E. J. GIBSON;
ROSALIE L. SIEN, and husband, A. C. SIEN, Jr</Grantor>
</From_1>
</From>
</tblPersonOfInterest>
</ROW_Easement>
假设 格式正确 XML 输入,您可以使用这个简单的 XSLT-3.0 代码。它将所有元素的名称替换为 @Name
属性,并且仅从输出中删除该属性。其余部分按原样复制 xsl:mode
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:mode on-no-match="shallow-copy" />
<xsl:template match="Document">
<ROW_Easement>
<xsl:apply-templates select="node()|@*" />
</ROW_Easement>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:apply-templates select="node()|@*[local-name()!='Name']" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
输出为:
<?xml version="1.0" encoding="UTF-8"?>
<ROW_Easement Id="0c744468-67d8-4daa-8ff9-cbd23209c59d"
Name="ROW_Easement (1)"
TypeId="adde4dc1-0710-452a-82c7-9e5ac1bafe94"
TypeName="ROW_Easement"
OriginalName="106-19-47A.pdf"
MimeType="application/pdf">
<File_Name Confidence="1.00" Page="1" Valid="True">106-19-47A</File_Name>
<tblPersonOfInterest>
<From Count="4">
<From_1>
<Grantor>
</Grantor>
</From_1>
</From>
</tblPersonOfInterest>
</ROW_Easement>
这可能不是最优雅的解决方案,但使用@zx485 的回答我将我的 XSLT 更改为:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:mode on-no-match="shallow-copy" />
<!-- Remove unnecessary attributes -->
<xsl:template match="@Confidence" />
<xsl:template match="@Id" />
<xsl:template match="@TypeId" />
<xsl:template match="@TypeName" />
<xsl:template match="@OriginalName" />
<xsl:template match="@MimeType" />
<xsl:template match="@Page" />
<xsl:template match="@Valid" />
<xsl:template match="@Count" />
<xsl:template match="@Location" />
<!-- Rename nodes -->
<xsl:template match="Document">
<ROW_Easement>
<xsl:apply-templates select="node()|@*" />
</ROW_Easement>
</xsl:template>
<!-- Copy to new XML -->
<xsl:template match="*">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:apply-templates select="node()|@*[local-name()!='Name']" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
现在可以使用了!如果有人愿意提供改进方法,仍然愿意提出建议。谢谢大家
没有说明您想保留哪些属性,但根据您的示例输入和您后来发布的代码,您似乎不想保留任何属性,但 Name
上的一个 Document
所以
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:template match="Document">
<ROW_Easement Name="{@Name}">
<xsl:apply-templates/>
</ROW_Easement>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
可能会更短并且避免列出所有您不想复制的属性。
我有这个xml:
<?xml version="1.0" encoding="utf-8"?>
<Document Id="0c744468-67d8-4daa-8ff9-cbd23209c59d" Name="ROW_Easement (1)" TypeId="adde4dc1-0710-452a-82c7-9e5ac1bafe94" TypeName="ROW_Easement" OriginalName="106-19-47A.pdf" MimeType="application/pdf">
<Field Name="File Name" Confidence="1.00" Page="1" Valid="True">106-19-47A</Field>
<Section Name="tblPersonOfInterest">
<SectionCollection Name="From" Count="4">
<Section Name="From 1">
<Field Name="Grantor" Confidence="1.00" Page="1" Valid="True" Location="1.713, 8.200, 6.487, 0.500">MARY E. GIBSON, and husband, E. J. GIBSON;
ROSALIE L. SIEN, and husband, A. C. SIEN, Jr</Field>
</Section>
</SectionCollection>
</Section>
</Document>
我想用“名称”属性值替换所有节点名称。到目前为止我有:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<ROW_Easement>
<xsl:for-each select="Field">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:value-of select="self::node()" />
</xsl:element>
</xsl:for-each>
<xsl:for-each select="Section">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:value-of select="self::node()" />
</xsl:element>
</xsl:for-each>
<xsl:for-each select="SectionCollection">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:value-of select="self::node()" />
</xsl:element>
</xsl:for-each>
</ROW_Easement>
</xsl:template>
</xsl:stylesheet>
结果是:
<?xml version="1.0" encoding="utf-8"?>
<ROW_Easement>
<File_Name>106-19-47A</File_Name>
<tblPersonOfInterest>
MARY E. GIBSON, and husband, E. J. GIBSON;
ROSALIE L. SIEN, and husband, A. C. SIEN, Jr
</tblPersonOfInterest>
</ROW_Easement>
它在 SectionCollection 节点中断,但我不明白为什么。
根据@michael.hor257k 的建议更新 更新:使用我现在得到的第一个建议:
<?xml version="1.0" encoding="utf-8"?><ROW_Easement>0c744468-67d8-4daa-8ff9-cbd23209c59dROW_Easement (1)adde4dc1-0710-452a-82c7-9e5ac1bafe94ROW_Easement106-19-47A.pdfapplication/pdf
<File_Name>1.001True106-19-47A</File_Name>
<tblPersonOfInterest>
<From>4
<From_1>
<Grantor>1.001True1.713, 8.200, 6.487, 0.500MARY E. GIBSON, and husband, E. J. GIBSON;
ROSALIE L. SIEN, and husband, A. C. SIEN, Jr</Grantor>
</From_1>
</From>
</tblPersonOfInterest>
</ROW_Easement>
假设 格式正确 XML 输入,您可以使用这个简单的 XSLT-3.0 代码。它将所有元素的名称替换为 @Name
属性,并且仅从输出中删除该属性。其余部分按原样复制 xsl:mode
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:mode on-no-match="shallow-copy" />
<xsl:template match="Document">
<ROW_Easement>
<xsl:apply-templates select="node()|@*" />
</ROW_Easement>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:apply-templates select="node()|@*[local-name()!='Name']" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
输出为:
<?xml version="1.0" encoding="UTF-8"?>
<ROW_Easement Id="0c744468-67d8-4daa-8ff9-cbd23209c59d"
Name="ROW_Easement (1)"
TypeId="adde4dc1-0710-452a-82c7-9e5ac1bafe94"
TypeName="ROW_Easement"
OriginalName="106-19-47A.pdf"
MimeType="application/pdf">
<File_Name Confidence="1.00" Page="1" Valid="True">106-19-47A</File_Name>
<tblPersonOfInterest>
<From Count="4">
<From_1>
<Grantor>
</Grantor>
</From_1>
</From>
</tblPersonOfInterest>
</ROW_Easement>
这可能不是最优雅的解决方案,但使用@zx485 的回答我将我的 XSLT 更改为:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:mode on-no-match="shallow-copy" />
<!-- Remove unnecessary attributes -->
<xsl:template match="@Confidence" />
<xsl:template match="@Id" />
<xsl:template match="@TypeId" />
<xsl:template match="@TypeName" />
<xsl:template match="@OriginalName" />
<xsl:template match="@MimeType" />
<xsl:template match="@Page" />
<xsl:template match="@Valid" />
<xsl:template match="@Count" />
<xsl:template match="@Location" />
<!-- Rename nodes -->
<xsl:template match="Document">
<ROW_Easement>
<xsl:apply-templates select="node()|@*" />
</ROW_Easement>
</xsl:template>
<!-- Copy to new XML -->
<xsl:template match="*">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:apply-templates select="node()|@*[local-name()!='Name']" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
现在可以使用了!如果有人愿意提供改进方法,仍然愿意提出建议。谢谢大家
没有说明您想保留哪些属性,但根据您的示例输入和您后来发布的代码,您似乎不想保留任何属性,但 Name
上的一个 Document
所以
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:template match="Document">
<ROW_Easement Name="{@Name}">
<xsl:apply-templates/>
</ROW_Easement>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{translate(@Name, ' ', '_')}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
可能会更短并且避免列出所有您不想复制的属性。