XSLT - 如何在使用流从变量节点进行内部循环时复制父节点?
XSLT - How can I copy parent node when inside loop from a variable node using streaming?
在迭代循环中使用模板匹配进行流式传输时,我正在努力复制我的父节点数据,该路径来自另一个 xml 我通过地图访问。
我得到的是:
<?xml version='1.0' encoding='utf-8'?>
<root>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
<Status>Error: Invalid ID value. '' is not a valid ID value for type =
'Custom_Worktag_13_ID'. Error: Invalid ID value. '' is not a valid ID value for type =
'Custom_Organization_Reference_ID'. Error: Invalid ID value. '133746-GP OM Internal
Labor-1' is not a valid ID value for type = 'Project_Plan_ID'. Error: Invalid ID value.
'12345' is not a valid ID value for type = 'Employee_ID'.</Status>
</row>
</root>
但我正在寻找的输出是:
<?xml version='1.0' encoding='utf-8'?>
<root>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
<Status>Error: Invalid ID value. '' is not a valid ID value for type =
'Custom_Worktag_13_ID'.</Status>
</row>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
<Status>Error: Invalid ID value. '' is not a valid ID value for type =
'Custom_Organization_Reference_ID'.</Status>
</row>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
<Status>Error: Invalid ID value. '133746-GP OM Internal Labor-1' is not a valid ID value for
type = 'Project_Plan_ID'.</Status>
</row>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
<Status>Error: Invalid ID value. '12345' is not a valid ID value for type =
'Employee_ID'.</Status>
</row>
</root>
XSLT 输入XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
</row>
</root>
错误变量数据:
<?xml version="1.0" encoding="UTF-8"?>
<errors>
<error>
<lineNumber>1</lineNumber>
<errorGroup>
<errorRow>
<severity>Error</severity>
<message>Invalid ID value. '' is not a valid ID value for type =
'Custom_Worktag_13_ID'</message>
</errorRow>
<errorRow>
<severity>Error</severity>
<message>Invalid ID value. '' is not a valid ID value for type =
'Custom_Organization_Reference_ID'</message>
</errorRow>
<errorRow>
<severity>Error</severity>
<message>Invalid ID value. '133746-GP OM Internal Labor-1' is not a valid ID value
for type = 'Project_Plan_ID'</message>
</errorRow>
<errorRow>
<severity>Error</severity>
<message>Invalid ID value. '12345' is not a valid ID value for type =
'Employee_ID'</message>
</errorRow>
</errorGroup>
</error>
</errors>
当前的 XSLT 3 代码:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map" version="3.0">
<xsl:output method="xml" indent="yes"/>
<xsl:mode name="streaming" streamable="yes" on-no-match="shallow-skip"/>
<xsl:mode name="in-memory" streamable="no"/>
<xsl:variable name="lineKey" as="map(xs:string, element())">
<xsl:map>
<xsl:call-template name="generateErrorFileMap"/>
</xsl:map>
</xsl:variable>
<xsl:template match="root">
<root>
<xsl:apply-templates select="row/copy-of()" mode="in-memory"/>
</root>
</xsl:template>
<xsl:template match="row" mode="in-memory">
<xsl:choose>
<xsl:when test="map:contains($lineKey, Record)">
<xsl:iterate select="map:get($lineKey, Record)/errorGroup/errorRow">
<row>
<!-- Copy Nodes -->
<xsl:apply-templates/>
<Status>
<xsl:value-of select="concat(severity, ': ', message, '.')"/>
</Status>
</row>
</xsl:iterate>
</xsl:when>
<xsl:otherwise>
<row>
<!-- Copy Nodes -->
<xsl:apply-templates/>
<status>
<xsl:value-of select="'Successfully loaded.'"/>
</status>
</row>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- standard copy template -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template name="generateErrorFileMap">
<xsl:source-document href="mctx:vars/errorFile" streamable="yes">
<xsl:for-each select="/errors/error/copy-of()">
<xsl:map-entry key="lineNumber => string()">
<map>
<xsl:apply-templates select="errorGroup"/>
</map>
</xsl:map-entry>
</xsl:for-each>
</xsl:source-document>
</xsl:template>
</xsl:stylesheet>
以优化方式实现我想要的输出的最佳方法是什么?
我认为
的结果
<xsl:apply-templates select="errorGroup"/>
将是一个 errorGroup
元素,这意味着 map:get($lineKey, Record)
的结果将是一个 errorGroup
元素,这意味着 map:get($lineKey, Record)/errorGroup
将 select 没有(因为 errorGroup
元素没有 errorGroup
子元素)。尝试将映射的类型声明更改为as="map(xs:string, element(errorGroup))"
以加强类型检查。
这是我在快速代码检查中唯一注意到的事情,但您没有告诉我们它是如何失败的;很难诊断一个看不见的问题。
我认为这是 xsl:merge
的任务(至少如果行和错误按 lineNumber 和 Record 整数值排序):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:output method="xml" indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template name="xsl:initial-template">
<root>
<xsl:merge>
<xsl:merge-source name="record" for-each-source="'record-list.xml'" streamable="yes" select="root/row">
<xsl:merge-key select="xs:integer(Record)"/>
</xsl:merge-source>
<xsl:merge-source name="error" for-each-source="'error-list.xml'" streamable="yes" select="errors/error">
<xsl:merge-key select="xs:integer(lineNumber)"/>
</xsl:merge-source>
<xsl:merge-action>
<xsl:choose>
<xsl:when test="not(current-merge-group('error'))">
<xsl:apply-templates select="current-merge-group('record')">
<xsl:with-param name="status" select="'Successfully loaded.'"/>
</xsl:apply-templates>
</xsl:when>
<xsl:when test="current-merge-group('record') and current-merge-group('error')">
<xsl:for-each select="current-merge-group('error')/errorGroup/errorRow">
<xsl:apply-templates select="current-merge-group('record')">
<xsl:with-param name="status" select="severity || ':' || message"/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:when>
</xsl:choose>
</xsl:merge-action>
</xsl:merge>
</root>
<xsl:comment xmlns:saxon="http://saxon.sf.net/">Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
</xsl:template>
<xsl:template match="row/*[last()]">
<xsl:param name="status"/>
<xsl:next-match/>
<status>{$status}</status>
</xsl:template>
</xsl:stylesheet>
运行 Saxon EE 使用 -it
选项而不是 -s
源选项。
修复原代码,我觉得不是
<xsl:when test="map:contains($lineKey, Record)">
<xsl:iterate select="map:get($lineKey, Record)/errorGroup/errorRow">
<row>
<!-- Copy Nodes -->
<xsl:apply-templates/>
<Status>
<xsl:value-of select="concat(severity, ': ', message, '.')"/>
</Status>
</row>
</xsl:iterate>
</xsl:when>
你想要例如
<xsl:variable name="record" select="."/>
<xsl:when test="map:contains($lineKey, Record)">
<xsl:iterate select="map:get($lineKey, Record)/errorGroup/errorRow">
<xsl:apply-templates select="$record">
<xsl:with-param name="status" select="severity || ': ' || message || '.'"/>
</xsl:apply-templates>
</xsl:iterate>
</xsl:when>
加一个模板(范围内需要 expand-text="yes"
)
<xsl:template match="row/*[last()]">
<xsl:param name="status"/>
<xsl:next-match/>
<status>{$status}</status>
</xsl:template>
在迭代循环中使用模板匹配进行流式传输时,我正在努力复制我的父节点数据,该路径来自另一个 xml 我通过地图访问。
我得到的是:
<?xml version='1.0' encoding='utf-8'?>
<root>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
<Status>Error: Invalid ID value. '' is not a valid ID value for type =
'Custom_Worktag_13_ID'. Error: Invalid ID value. '' is not a valid ID value for type =
'Custom_Organization_Reference_ID'. Error: Invalid ID value. '133746-GP OM Internal
Labor-1' is not a valid ID value for type = 'Project_Plan_ID'. Error: Invalid ID value.
'12345' is not a valid ID value for type = 'Employee_ID'.</Status>
</row>
</root>
但我正在寻找的输出是:
<?xml version='1.0' encoding='utf-8'?>
<root>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
<Status>Error: Invalid ID value. '' is not a valid ID value for type =
'Custom_Worktag_13_ID'.</Status>
</row>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
<Status>Error: Invalid ID value. '' is not a valid ID value for type =
'Custom_Organization_Reference_ID'.</Status>
</row>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
<Status>Error: Invalid ID value. '133746-GP OM Internal Labor-1' is not a valid ID value for
type = 'Project_Plan_ID'.</Status>
</row>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
<Status>Error: Invalid ID value. '12345' is not a valid ID value for type =
'Employee_ID'.</Status>
</row>
</root>
XSLT 输入XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<Record>1</Record>
<Employee-ID>12345</Employee-ID>
<Authorization-ID>133746</Authorization-ID>
<Date>2021-06-22</Date>
<Quantity>2</Quantity>
<Task-ID>PRJTASK0011134</Task-ID>
<Project-Plan-ID>133746-GP OM Internal Labor-1</Project-Plan-ID>
<Comments/>
</row>
</root>
错误变量数据:
<?xml version="1.0" encoding="UTF-8"?>
<errors>
<error>
<lineNumber>1</lineNumber>
<errorGroup>
<errorRow>
<severity>Error</severity>
<message>Invalid ID value. '' is not a valid ID value for type =
'Custom_Worktag_13_ID'</message>
</errorRow>
<errorRow>
<severity>Error</severity>
<message>Invalid ID value. '' is not a valid ID value for type =
'Custom_Organization_Reference_ID'</message>
</errorRow>
<errorRow>
<severity>Error</severity>
<message>Invalid ID value. '133746-GP OM Internal Labor-1' is not a valid ID value
for type = 'Project_Plan_ID'</message>
</errorRow>
<errorRow>
<severity>Error</severity>
<message>Invalid ID value. '12345' is not a valid ID value for type =
'Employee_ID'</message>
</errorRow>
</errorGroup>
</error>
</errors>
当前的 XSLT 3 代码:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map" version="3.0">
<xsl:output method="xml" indent="yes"/>
<xsl:mode name="streaming" streamable="yes" on-no-match="shallow-skip"/>
<xsl:mode name="in-memory" streamable="no"/>
<xsl:variable name="lineKey" as="map(xs:string, element())">
<xsl:map>
<xsl:call-template name="generateErrorFileMap"/>
</xsl:map>
</xsl:variable>
<xsl:template match="root">
<root>
<xsl:apply-templates select="row/copy-of()" mode="in-memory"/>
</root>
</xsl:template>
<xsl:template match="row" mode="in-memory">
<xsl:choose>
<xsl:when test="map:contains($lineKey, Record)">
<xsl:iterate select="map:get($lineKey, Record)/errorGroup/errorRow">
<row>
<!-- Copy Nodes -->
<xsl:apply-templates/>
<Status>
<xsl:value-of select="concat(severity, ': ', message, '.')"/>
</Status>
</row>
</xsl:iterate>
</xsl:when>
<xsl:otherwise>
<row>
<!-- Copy Nodes -->
<xsl:apply-templates/>
<status>
<xsl:value-of select="'Successfully loaded.'"/>
</status>
</row>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- standard copy template -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template name="generateErrorFileMap">
<xsl:source-document href="mctx:vars/errorFile" streamable="yes">
<xsl:for-each select="/errors/error/copy-of()">
<xsl:map-entry key="lineNumber => string()">
<map>
<xsl:apply-templates select="errorGroup"/>
</map>
</xsl:map-entry>
</xsl:for-each>
</xsl:source-document>
</xsl:template>
</xsl:stylesheet>
以优化方式实现我想要的输出的最佳方法是什么?
我认为
的结果<xsl:apply-templates select="errorGroup"/>
将是一个 errorGroup
元素,这意味着 map:get($lineKey, Record)
的结果将是一个 errorGroup
元素,这意味着 map:get($lineKey, Record)/errorGroup
将 select 没有(因为 errorGroup
元素没有 errorGroup
子元素)。尝试将映射的类型声明更改为as="map(xs:string, element(errorGroup))"
以加强类型检查。
这是我在快速代码检查中唯一注意到的事情,但您没有告诉我们它是如何失败的;很难诊断一个看不见的问题。
我认为这是 xsl:merge
的任务(至少如果行和错误按 lineNumber 和 Record 整数值排序):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:output method="xml" indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template name="xsl:initial-template">
<root>
<xsl:merge>
<xsl:merge-source name="record" for-each-source="'record-list.xml'" streamable="yes" select="root/row">
<xsl:merge-key select="xs:integer(Record)"/>
</xsl:merge-source>
<xsl:merge-source name="error" for-each-source="'error-list.xml'" streamable="yes" select="errors/error">
<xsl:merge-key select="xs:integer(lineNumber)"/>
</xsl:merge-source>
<xsl:merge-action>
<xsl:choose>
<xsl:when test="not(current-merge-group('error'))">
<xsl:apply-templates select="current-merge-group('record')">
<xsl:with-param name="status" select="'Successfully loaded.'"/>
</xsl:apply-templates>
</xsl:when>
<xsl:when test="current-merge-group('record') and current-merge-group('error')">
<xsl:for-each select="current-merge-group('error')/errorGroup/errorRow">
<xsl:apply-templates select="current-merge-group('record')">
<xsl:with-param name="status" select="severity || ':' || message"/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:when>
</xsl:choose>
</xsl:merge-action>
</xsl:merge>
</root>
<xsl:comment xmlns:saxon="http://saxon.sf.net/">Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
</xsl:template>
<xsl:template match="row/*[last()]">
<xsl:param name="status"/>
<xsl:next-match/>
<status>{$status}</status>
</xsl:template>
</xsl:stylesheet>
运行 Saxon EE 使用 -it
选项而不是 -s
源选项。
修复原代码,我觉得不是
<xsl:when test="map:contains($lineKey, Record)">
<xsl:iterate select="map:get($lineKey, Record)/errorGroup/errorRow">
<row>
<!-- Copy Nodes -->
<xsl:apply-templates/>
<Status>
<xsl:value-of select="concat(severity, ': ', message, '.')"/>
</Status>
</row>
</xsl:iterate>
</xsl:when>
你想要例如
<xsl:variable name="record" select="."/>
<xsl:when test="map:contains($lineKey, Record)">
<xsl:iterate select="map:get($lineKey, Record)/errorGroup/errorRow">
<xsl:apply-templates select="$record">
<xsl:with-param name="status" select="severity || ': ' || message || '.'"/>
</xsl:apply-templates>
</xsl:iterate>
</xsl:when>
加一个模板(范围内需要 expand-text="yes"
)
<xsl:template match="row/*[last()]">
<xsl:param name="status"/>
<xsl:next-match/>
<status>{$status}</status>
</xsl:template>