XSL 转换 xml 元素名称中包含字符实体
XSL transform an xml with character entities in element names
我的 xml 看起来像:
<record>
<name>ABC</name>
<address>
<street>sss</street>
<city>ccc</city>
<state>ttt</state>
</address>
</record>
我正在尝试使用 xsl:
读取元素 'street'
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="/">
<xsl:value-of select="record/address/street" />
</xsl:template>
</xsl:stylesheet>
但它没有给出任何输出。
为什么即使输入 xml 是有效的 xml 格式也会发生这种情况?
那么如何转换 xml 个包含元素名称字符实体的文件呢?
<xsl:template match="//name"/>
<xsl:template match="record/address">
<xsl:value-of select="substring-before(., '<city>ccc</city>')" disable-output-escaping="yes"/>
</xsl:template>
检查此代码。
没有 street
元素。如果它被写成 <street>...</street>
那么它将是一个元素,但是尖括号已经被小心地转义以表明它应该被视为纯文本。
将包含尖括号的纯文本转换为XML节点结构涉及解析;也就是说,您需要对 address
元素的文本内容执行第二次解析。由于您在此处拥有的是 XML 片段而不是完整的 XML 文档,因此这很复杂。
在 XSLT 3.0 中,您可以使用 parse-xml-fragment() 函数实现此目的。在早期版本中,您可以通过调用自定义扩展函数来实现它,或者(如@sandeepkamboj 所建议的那样)通过在 XSLT 中编写一个简单的 XML 解析器(为此,您需要确信自己知道您需要处理 XML 构造的哪个子集)。
也许最好的方法是找出为什么有人生成了这个荒谬的文件,并让他们改过自新。
添加到 Michael Kay 的回答:
如果您首先使用以下方法处理 XML:
XSLT 1.0
<xsl:stylesheet version="1.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="address">
<xsl:copy>
<xsl:value-of select="." disable-output-escaping="yes"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
并将结果保存到文件中,然后您将能够使用您的样式表来处理生成的文件并获得预期的结果。
我的 xml 看起来像:
<record>
<name>ABC</name>
<address>
<street>sss</street>
<city>ccc</city>
<state>ttt</state>
</address>
</record>
我正在尝试使用 xsl:
读取元素 'street'<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="/">
<xsl:value-of select="record/address/street" />
</xsl:template>
</xsl:stylesheet>
但它没有给出任何输出。
为什么即使输入 xml 是有效的 xml 格式也会发生这种情况? 那么如何转换 xml 个包含元素名称字符实体的文件呢?
<xsl:template match="//name"/>
<xsl:template match="record/address">
<xsl:value-of select="substring-before(., '<city>ccc</city>')" disable-output-escaping="yes"/>
</xsl:template>
检查此代码。
没有 street
元素。如果它被写成 <street>...</street>
那么它将是一个元素,但是尖括号已经被小心地转义以表明它应该被视为纯文本。
将包含尖括号的纯文本转换为XML节点结构涉及解析;也就是说,您需要对 address
元素的文本内容执行第二次解析。由于您在此处拥有的是 XML 片段而不是完整的 XML 文档,因此这很复杂。
在 XSLT 3.0 中,您可以使用 parse-xml-fragment() 函数实现此目的。在早期版本中,您可以通过调用自定义扩展函数来实现它,或者(如@sandeepkamboj 所建议的那样)通过在 XSLT 中编写一个简单的 XML 解析器(为此,您需要确信自己知道您需要处理 XML 构造的哪个子集)。
也许最好的方法是找出为什么有人生成了这个荒谬的文件,并让他们改过自新。
添加到 Michael Kay 的回答:
如果您首先使用以下方法处理 XML:
XSLT 1.0
<xsl:stylesheet version="1.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="address">
<xsl:copy>
<xsl:value-of select="." disable-output-escaping="yes"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
并将结果保存到文件中,然后您将能够使用您的样式表来处理生成的文件并获得预期的结果。