我有一个xml数据文件。我还有一个转换该文件的xslt文件。这是我现在拥有的。原始的xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="file:///C:/Users/chvl/Desktop/New%20folder%20(2)/UntitledDS.xslt"?>
<L4 type="schema" guid="de2f8f94-8db6-4979-b32f-8db4bfac3f3c" versionNumber="16" DpaLength="4">
<L4 type="group">
<FirmID type="item">
<value>872</value>
</FirmID>
<FirmName type="item">
<value>Generic Name Here</value>
</FirmName>
<FirmRef type="item">
<value>LC</value>
</FirmRef>
<ReportingEndDate type="item">
<value>2015-05-31</value>
</ReportingEndDate>
<L4 type="group">
<_x0030_257 type="item">
<value xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</_x0030_257>
<_x0030_258 type="item">
<value>1791886</value>
</_x0030_258>
<_x0030_725 type="item">
<value xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</_x0030_725>
<_x0030_726 type="item">
<value>407897</value>
</_x0030_726>
</L4>
</L4>
</L4>
这是通过xslt
后的新xml文件<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="file:///C:/Users/chvl/Desktop/New%20folder%20(2)/UntitledDS.xslt"?>
<Root xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" name="L4" type="schema" guid="de2f8f94-8db6-4979-b32f-8db4bfac3f3c" versionNumber="16" DpaLength="4">
<Main name="L4" type="group">
<FirmID type="item">
<value>872</value>
</FirmID>
<FirmName type="item">
<value>Generic Name Here</value>
</FirmName>
<FirmRef type="item">
<value>LC</value>
</FirmRef>
<ReportingEndDate type="item">
<value>2015-05-31</value>
</ReportingEndDate>
<Data name="L4" type="group">
<DataItem dpa="_x0030_257">
<value></value>
</DataItem>
<DataItem dpa="_x0030_258">
<value>1791886</value>
</DataItem>
<DataItem dpa="_x0030_725">
<value></value>
</DataItem>
<DataItem dpa="_x0030_726">
<value>407897</value>
</DataItem>
</Data>
</Main>
</Root>
在原始的xml中,您会看到子元素,其中xsi:nil =&#34; true&#34;?好吧,当发生这种情况时,我需要删除它的父元素。在此示例中,我需要删除&lt; _x0030_257 type =&#34; item&#34;&gt;和&lt; _x0030_725 type =&#34; item&#34;&gt;及其所有子要素。
现在,我尝试过将此代码放在XSLT的末尾。
<xsl:template match="/*/*/*/node()[./*/(@xsi:nil = 'true')]|@*">/xsl:template>
它可以工作,除了它还从我的根元素以及其他地方删除属性。但我需要所有这些属性。我觉得我离解决这个问题只有一步之遥,但这一步骤正在成为一次巨大的飞跃。
任何帮助都将不胜感激。
以下是带有代码段代码的完整XSLT,用于删除nil父元素(上面的示例未使用代码段运行以删除nils)。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/*">
<Root>
<xsl:attribute name="name" >
<xsl:value-of select="name(.)"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="/*[type='schema']">
<xsl:apply-templates select="ignore"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="@*|node()"/>
</xsl:otherwise>
</xsl:choose>
</Root>
</xsl:template>
<xsl:template match="/*/*[@type='group']">
<Main>
<xsl:attribute name="name" >
<xsl:value-of select="name(.)"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="child::*[type='item']">
<xsl:apply-templates select="ignore"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="@*|node()"/>
</xsl:otherwise>
</xsl:choose>
</Main>
</xsl:template>
<xsl:template match="/*/*/*[@type='group']">
<Data>
<xsl:attribute name="name" >
<xsl:value-of select="name(.)"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="child::*[type='item']">
<xsl:apply-templates select="ignore"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="@*|node()"/>
</xsl:otherwise>
</xsl:choose>
</Data>
</xsl:template>
<xsl:template match="/*/*/*[@type='list']">
<Cube>
<xsl:attribute name="name" >
<xsl:value-of select="name(.)"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="child::*[type='item']">
<xsl:apply-templates select="ignore"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="@*|node()"/>
</xsl:otherwise>
</xsl:choose>
</Cube>
</xsl:template>
<xsl:template match="/*/*/Filters[@type='group']"/>
<xsl:template match="/*/*/*/*[@type='group']">
<xsl:variable name="count">
<xsl:number/>
</xsl:variable>
<Data grpcnt="{$count}">
<xsl:attribute name="name" >
<xsl:value-of select="name(.)"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="child::*[type='item']">
<xsl:apply-templates select="ignore"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="@*|node()"/>
</xsl:otherwise>
</xsl:choose>
</Data>
</xsl:template>
<xsl:template match="*/*/*/*[@type='item']">
<DataItem>
<xsl:attribute name="dpa" >
<xsl:value-of select="name(.)"/>
</xsl:attribute>
<value><xsl:value-of select="value"/></value>
</DataItem>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*/*/*/node()[./*/(@xsi:nil = 'true')]|@*">
</xsl:template>
</xsl:stylesheet>
PS:请记住,元素名称改变了我使用星号而不是硬编码标签名称的原因。
答案 0 :(得分:2)
我认为只从最后一个模板的模板匹配中删除|@*
可能会解决问题:
<xsl:template match="/*/*/*/node()[./*/(@xsi:nil = 'true')]">
它可以工作,除了它还从我的根元素以及其他地方删除属性。
那是因为在你的原始表达中:
/*/*/*/node()[./*/(@xsi:nil = 'true')] | @*
|
或“union”表示以下内容:|
左侧的所有内容或其右侧的所有内容(假设只有一个此类符号)。
因此,表达式意味着:在文档中的任何位置具有真实nil
属性 OR 任何属性的节点。
既然你在问题中提到了“humongous”,那么你的表达是:
/*/*/*/node()[./*/(@xsi:nil = 'true')]
也非常棒。如果嵌套级别非常重要,并且您希望在其他位置保留元素/*/*/*/
,则仅使用nil="true"
。
如果嵌套不重要,最终会以
结束node()[./*/(@xsi:nil = 'true')]
然后,node()
过于笼统,因为它是对任何类型节点的测试,而不仅仅是元素节点。使用*
代替引用元素:
*[./*/(@xsi:nil = 'true')]
在谓词([...]
)中,没有必要以./
开头,因为无论如何都隐含地假设了这个上下文:
*[*/(@xsi:nil = 'true')
不需要括号:
*[*/@xsi:nil = 'true']
如果xsi:nil
属性仅属于,当其值为“true”时,您甚至可以写
*[*/@xsi:nil]
关于这个表达式的最后一句话:我猜你在表达式中包含|@*
,因为你还想排除这些元素的所有属性,对吧?
<xsl:template match="*[*/@xsi:nil]"/>
不会处理这些元素的任何属性或内容。
正如用户wero指出的那样,您还需要在XSLT样式表中声明XSI名称空间以使其正常工作:
<xsl:stylesheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
更一般的建议:似乎你从文档节点开始所有模板匹配,使模式绝对。如果您是故意这样做的话,这很好,但它也限制了XSLT样式表的多功能性。