XSLT - 转换几个兄弟标签,但保持其余部分不变
XSLT - transform several sibling tags, but keep the rest intact
我正在尝试转换我的 输入 XML:
<?xml version="1.0" encoding="utf-8"?>
<request>
<customer_data>
<contact_info>
<name>john doe</name>
<dob_year>1984</dob_year>
<dob_month>09</dob_month>
<dob_date>14</dob_date>
<gender>m</gender>
</contact_info>
</customer_data>
</request>
所以它看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<request>
<customer_data>
<contact_info>
<name>john doe</name>
<dob>1984-09-14</dob>
<gender>m</gender>
</contact_info>
</customer_data>
</request>
这是我正在使用的 XSLT:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="contact_info">
<xsl:copy>
<dob>
<xsl:value-of select="(dob_year, dob_month, dob_date)" separator="-"/>
</dob>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这是我得到的结果:
<?xml version="1.0" encoding="utf-8"?><request>
<customer_data>
<contact_info><dob>1984-09-14</dob></contact_info>
</customer_data>
</request>
如何转换 dob_* 标签,保持 contact_info 的其余部分完整?
更新
根据下面的答案,我目前的解决方案是
<xsl:template match="contact_info">
<xsl:copy>
<xsl:apply-templates select="*[not(starts-with(name(), 'dob'))]"/>
<dob>
<xsl:value-of select="(dob_year, dob_month, dob_date)" separator="-"/>
</dob>
</xsl:copy>
</xsl:template>
这对我有用,但是没有更优雅的方式来表达“对给定元素应用转换,对其余元素应用模板”吗?现在,我有点被这个表达式 *[not(starts-with(name(), 'dob'))]
困住了,这还不错,但是如果 "DOB" 属性的名称发生变化,我也必须修复它。
改变
<xsl:template match="contact_info">
<xsl:copy>
<dob>
<xsl:value-of select="(dob_year, dob_month, dob_date)" separator="-"/>
</dob>
</xsl:copy>
</xsl:template>
至
<xsl:template match="contact_info">
<xsl:copy>
<xsl:apply-templates select="dob_year/preceding-sibling::node()"/>
<dob>
<xsl:value-of select="(dob_year, dob_month, dob_date)" separator="-"/>
</dob>
<xsl:apply-templates select="dob_date/following-sibling::node()"/>
</xsl:copy>
</xsl:template>
这是您可以查看的一种方式:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="dob_year">
<dob>
<xsl:value-of select="(., ../dob_month, ../dob_date)" separator="-"/>
</dob>
</xsl:template>
<xsl:template match="dob_month|dob_date"/>
</xsl:stylesheet>
这是另一个:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="contact_info">
<xsl:copy>
<xsl:copy-of select="name|gender"/>
<dob>
<xsl:value-of select="(dob_year, dob_month, dob_date)" separator="-"/>
</dob>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
编辑:
为了仅枚举 DOB 元素并且只枚举一次,您可以这样做:
<xsl:template match="contact_info">
<xsl:variable name="dob-fields" select="(dob_year, dob_month, dob_date)" />
<xsl:copy>
<xsl:apply-templates select="* except $dob-fields"/>
<dob>
<xsl:value-of select="$dob-fields" separator="-"/>
</dob>
</xsl:copy>
</xsl:template>
我正在尝试转换我的 输入 XML:
<?xml version="1.0" encoding="utf-8"?>
<request>
<customer_data>
<contact_info>
<name>john doe</name>
<dob_year>1984</dob_year>
<dob_month>09</dob_month>
<dob_date>14</dob_date>
<gender>m</gender>
</contact_info>
</customer_data>
</request>
所以它看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<request>
<customer_data>
<contact_info>
<name>john doe</name>
<dob>1984-09-14</dob>
<gender>m</gender>
</contact_info>
</customer_data>
</request>
这是我正在使用的 XSLT:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="contact_info">
<xsl:copy>
<dob>
<xsl:value-of select="(dob_year, dob_month, dob_date)" separator="-"/>
</dob>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这是我得到的结果:
<?xml version="1.0" encoding="utf-8"?><request>
<customer_data>
<contact_info><dob>1984-09-14</dob></contact_info>
</customer_data>
</request>
如何转换 dob_* 标签,保持 contact_info 的其余部分完整?
更新
根据下面的答案,我目前的解决方案是
<xsl:template match="contact_info">
<xsl:copy>
<xsl:apply-templates select="*[not(starts-with(name(), 'dob'))]"/>
<dob>
<xsl:value-of select="(dob_year, dob_month, dob_date)" separator="-"/>
</dob>
</xsl:copy>
</xsl:template>
这对我有用,但是没有更优雅的方式来表达“对给定元素应用转换,对其余元素应用模板”吗?现在,我有点被这个表达式 *[not(starts-with(name(), 'dob'))]
困住了,这还不错,但是如果 "DOB" 属性的名称发生变化,我也必须修复它。
改变
<xsl:template match="contact_info">
<xsl:copy>
<dob>
<xsl:value-of select="(dob_year, dob_month, dob_date)" separator="-"/>
</dob>
</xsl:copy>
</xsl:template>
至
<xsl:template match="contact_info">
<xsl:copy>
<xsl:apply-templates select="dob_year/preceding-sibling::node()"/>
<dob>
<xsl:value-of select="(dob_year, dob_month, dob_date)" separator="-"/>
</dob>
<xsl:apply-templates select="dob_date/following-sibling::node()"/>
</xsl:copy>
</xsl:template>
这是您可以查看的一种方式:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="dob_year">
<dob>
<xsl:value-of select="(., ../dob_month, ../dob_date)" separator="-"/>
</dob>
</xsl:template>
<xsl:template match="dob_month|dob_date"/>
</xsl:stylesheet>
这是另一个:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="contact_info">
<xsl:copy>
<xsl:copy-of select="name|gender"/>
<dob>
<xsl:value-of select="(dob_year, dob_month, dob_date)" separator="-"/>
</dob>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
编辑:
为了仅枚举 DOB 元素并且只枚举一次,您可以这样做:
<xsl:template match="contact_info">
<xsl:variable name="dob-fields" select="(dob_year, dob_month, dob_date)" />
<xsl:copy>
<xsl:apply-templates select="* except $dob-fields"/>
<dob>
<xsl:value-of select="$dob-fields" separator="-"/>
</dob>
</xsl:copy>
</xsl:template>