基本XML/XSLT转换:搜索和;代替
我不熟悉XML和XSLT,并且花了一些时间研究了一个非常简单的搜索和替换案例。我只是不知道语法是否正确 本练习的总体目标是将元素“NewCustomer”中的“Y”和“N”的值分别替换为“true”或“false” 这是我的样本数据基本XML/XSLT转换:搜索和;代替,xml,xslt,Xml,Xslt,我不熟悉XML和XSLT,并且花了一些时间研究了一个非常简单的搜索和替换案例。我只是不知道语法是否正确 本练习的总体目标是将元素“NewCustomer”中的“Y”和“N”的值分别替换为“true”或“false” 这是我的样本数据 <?xml version="1.0"?> <CustomerList> <Customer> <CustomerID>1111</CustomerID> <CompanyName
<?xml version="1.0"?>
<CustomerList>
<Customer>
<CustomerID>1111</CustomerID>
<CompanyName>Sean Chai</CompanyName>
<City>New York</City>
<NewCustomer>N</NewCustomer>
</Customer>
<Customer>
<CustomerID>1112</CustomerID>
<CompanyName>Tom Johnston</CompanyName>
<City>Los Angeles</City>
<NewCustomer>N</NewCustomer>
</Customer>
<Customer>
<CustomerID>1113</CustomerID>
<CompanyName>Institute of Art</CompanyName>
<City>Chicago</City>
<NewCustomer>Y</NewCustomer>
</Customer>
</CustomerList>
1111
肖恩柴
纽约
N
1112
汤姆强斯顿
洛杉矶
N
1113
艺术学院
芝加哥
Y
这是转换样式表
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Identity Template (applies to all nodes and will copy all nodes -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Customer">
<xsl:choose>
<xsl:when test="NewCustomer = 'Y'">
<xsl:text>true</xsl:text>
</xsl:when>
<xsl:when test="NewCustomer = 'N'">
<xsl:text>false</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
真的
假的
这是我的输出
<?xml version="1.0" encoding="utf-8" ?>
<CustomerList>false false true</CustomerList>
假假假真
下面是我希望它输出的内容
<?xml version="1.0"?>
<CustomerList>
<Customer>
<CustomerID>1111</CustomerID>
<CompanyName>Sean Chai</CompanyName>
<City>New York</City>
<NewCustomer>false</NewCustomer>
</Customer>
<Customer>
<CustomerID>1112</CustomerID>
<CompanyName>Tom Johnston</CompanyName>
<City>Los Angeles</City>
<NewCustomer>false</NewCustomer>
</Customer>
<Customer>
<CustomerID>1113</CustomerID>
<CompanyName>Institute of Art</CompanyName>
<City>Chicago</City>
<NewCustomer>true</NewCustomer>
</Customer>
</CustomerList>
1111
肖恩柴
纽约
假的
1112
汤姆强斯顿
洛杉矶
假的
1113
艺术学院
芝加哥
真的
我错过了什么?为什么?我发现如果我省略了检查NewCustomer的子句,那么整个输出都会得到输出。但是,选择为NewCustomer输出正确更改的值只会显示这些值。我必须在第二个模板中引用上一个模板吗?通过让模板与客户匹配,您将拦截该标记的所有处理 尝试更改模板以仅匹配NewCustomer,并在测试条件中进行相应更改(test=“.=”Y') 还要注意,您必须在输出中创建NewCustomer标记,因为通过在自定义模板中匹配它,标识转换不会处理它。你很接近 以下是更新的模板:
<xsl:template match="Customer/NewCustomer">
<xsl:copy>
<xsl:choose>
<xsl:when test=". = 'Y'">
<xsl:text>true</xsl:text>
</xsl:when>
<xsl:when test=". = 'N'">
<xsl:text>false</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:copy>
</xsl:template>
真的
假的
首先,它将NewCustomer作为Customer的子级进行匹配。然后,它使用xsl:copy创建节点的副本(而不是属性或子节点)。然后使用xsl:choose将N和Y值分别转换为false和true
关键概念是,当模板与输入元素匹配时,输入元素将从输出中有效删除,并替换为匹配模板的内容。在您的案例中,当您匹配客户时,客户标签及其内部的所有内容都被模板的内容所替换,而模板的内容只是生成了“真”或“假”。吉姆·加里森回答中的精彩解释仍然适用。以下是一种浓缩/替代方法:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:choose>
<xsl:when test="self::NewCustomer">
<xsl:value-of select="boolean(number(translate(., 'YN', '10')))" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="@* | node()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
表达式boolean(number(translate(,'YN','10'))
将'Y'
更改为'1'
,将'N'
更改为'0'
,然后将其首先转换为数字,然后再转换为布尔值。布尔值将分别表示为'true'
或'false'
这有点脏,因为它实际上不处理除'Y'
或'N'
以外的值,但它将为'Y'
以外的任何值输出'false'
这只不过是节省空间而已。如果您愿意,您可以用Jim Garrison使用的
替换它。Jim Garrison将从任何新客户
元素中删除属性。而托马拉克的,正如他所说的,有点脏
此版本几乎是将您的需求直译为XSLT:
<xsl:stylesheet version="1.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="NewCustomer/text()[.='Y']">
<xsl:text>true</xsl:text>
</xsl:template>
<xsl:template match="NewCustomer/text()[.='N']">
<xsl:text>false</xsl:text>
</xsl:template>
</xsl:stylesheet>
真的
假的
源树中唯一没有准确复制到结果集中的节点是文本节点,这些节点是
NewCustomer
元素的子元素,其值为Y
或N
;对于这些,它分别发出true
和false
。+1完成这项任务的方法确实很多。我从给定的数据中“假设”了模式,没有复制属性。关于问题的“如何/为什么”部分,请参阅@JimGarrison答案。